在C中实现< 的另一种方法

js4nwp54  于 2023-10-16  发布在  其他
关注(0)|答案(2)|浏览(91)

我在编写正确的代码时遇到了麻烦,如果x < 5返回1 + x,否则返回1
问题规格:

  • 如果x < 5,则返回1 + x,否则返回1(这确保了1 <= f(x) <= 5
  • 示例counter1To5(2) = 3
  • 示例counter1To5(5) = 1
  • 允许用途:~&!|+<<>>
  • 操作员最大数量:15

这是我到目前为止所拥有的:

int counter1To5(int x) {
    return ((x + ~4) >> 31) & (x + 1);
}
zfciruhq

zfciruhq1#

我不打算发布一个完整的答案,但我猜你正在寻找的是某种 * 运算符 * 的方法来确定x是否大于5

!((x - 1) >> 2)

  ^    ^      ^
  |    |      |
  |    |    Here you shift the bits that are not necessary out of the integer
  |    |
  |  By subtracting here you make sure, that 5 is the smallest integer to not
  |  be shifted out
  |
 Negating the value to get 1 or 0 as an output

我没有测试,但如果x确实大于4,则应返回0,如果x小于5,则应返回1。注意,我不是一个Maven。我没有考虑负值,可能有更聪明的方法来解决你的问题。如果这是一个家庭作业,毫无疑问,你的教授会自豪地告诉你。
编辑:是的,>>对于可移植代码来说是有风险的,但这几乎不是他想在某个地方实现的真实的东西。

8zzbczxx

8zzbczxx2#

假设int具有2的补码表示(这应该是一个安全的假设,因为C23将要求有符号整数类型具有2的补码表示),此函数定义满足以下条件:当x < 5时应返回x + 1,当x >= 5时应返回1,仅使用~&!|+<<>>运算符,并且使用不超过15个运算符:

#include <limits.h>

int counter1To5(int x) {
    return (x & (!((x & ~INT_MAX) | !(x & ~4) | !(x & ~3)) + ~0)) + 1;
}

return表达式分解为:
1.当x < 0时,(x & ~INT_MAX)将是INT_MIN,当x >= 0时,0将是INT_MIN。(使用(x & INT_MIN)将保存一个显式运算符,但INT_MIN宏的扩展可能会引入一个运算符,该运算符可能是一元-运算符,这是禁止的。
1.当x == 0 || x == 4时,!(x & ~4)将是1,当x != 0 && x != 4时,0将是1
1.当x >= 0 && x < 4时,!(x & ~3)将是1,当x < 0 || x >= 4时,0将是1
1.或-ing 23 以上,!(x & ~4) | !(x & ~3)将是1时,x >= 0 && x < 5,或0时,x < 0 || x >= 5
1.或-ing 14 以上,(x & ~INT_MAX) | !(x & ~4) | !(x & ~3)将是INT_MIN时,x < 0,或1时,x >= 0 && x < 5,或0时,x >= 5(即。它将是非零的,当且仅当x < 5)。
1.从逻辑上否定上面的 5,当x >= 5时,!((x & ~INT_MAX) | !(x & ~4) | !(x & ~3))将是1,或者当x < 5时,0
1.从上面的 6 中减去1(通过将~0添加到),当x >= 5(!((x & ~INT_MAX) | !(x & ~4) | !(x & ~3)) + ~0)将是0,或者当x < 5-1
1.按位AND-ing x7 以上,(x & (!((x & ~INT_MAX) | !(x & ~4) | !(x & ~3)) + ~0))将是0时,x >= 5,或x时,x < 5
1.最后将1加到上面的 8(x & (!((x & ~INT_MAX) | !(x & ~4) | !(x & ~3)) + ~0)) + 1将在x >= 5时为1,或在x < 5时为x + 1
如果counter1To5(x)x < 0时也应该返回1,则函数定义可以简化为:

int counter1To5(int x) {
    return (x & (!(!(x & ~4) | !(x & ~3)) + ~0)) + 1;
}

相关问题