仅使用按位转换 long 和 int

标签 c bit-manipulation bitwise-operators

我正在尝试仅使用按位运算符来重现以下函数的输出! ~ & ^ | + << >>.

int test_dl2(int x, int y) { 
   long long lsum = (long long) x + y;
   return lsum == (int) lsum;
}

我所有的测试都表明所有问题的答案都只有 1。但是告诉您问题是否正确的自动测试器说只返回一个是不正确的。

在什么情况下答案不是 1? 如果函数没有像这样被复制:

int test_dl2(int x, int y) { 
   return 1;
}

正确的函数/表达式是什么(仅使用所述按位运算符)?

最佳答案

也许您正在尝试检查 xy 的相加是否会给出作为 uint32_t 的有效结果。如评论中所述,问题是如果数字太大,则从 uint64_t 到 uint32_t 的转换是未定义的。

目前,C 和 C++ 均不假定数字表示为二进制补码,因此很难进行这种验证。这将会改变,因为下一个 C++ 标准将强制使用 two's complement to code signed integers。 (而且 C 标准可能会随之而来)。

但这不会为不正确的转换赋予意义,您的代码仍然无效。

如果我们假设数字是用二进制补码编码的(这已经是大多数计算机的行为),则可以进行一些测试。

可以使用多种解决方案。这是一个主要依赖于按位运算符的方法。

方法的概要是:

  • 将数字左移以除以二(假设带符号的左移是算术运算,这在大多数计算机上都是正确的,但标准目前不需要)

  • 添加它们。这将计算 x/2+y/2 并且它将等于 (x+y)/2 except 如果 < em>x 和 y 是一个,在这种情况下,x+y 中的权重 2^1 处产生了一个进位。
    我们通过 anding xy 的 LSB 来测试此进位的存在,并将其添加到总和中。

  • 前面计算的结果 (x+y)/2 在 32 位上总是有效的。我们检查它在 31 位上是否有效。如果为真,x+y 将在 32 位上有效。
    只需比较第 31 位和第 30 位即可检查此有效性。如果它们相等,则可以安全地将结果转换为 31 位。否则,转换会引起符号变化。

int is_add32_valid(uint32_t x, uint32_t y) { 
  uint32_t z = (x>>1) + (y>>1) + (x & y & 0x1) ;
  return !( (z ^ (z <<1)) & (1 << 31) ) ;
}

关于仅使用按位转换 long 和 int,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58687759/

相关文章:

c - 变量在循环中途发生变化,我不知道是什么问题

c - C 中的 MPI_Testsome 和 MPI_Iprobe

c - append 在链表的末尾

c++ - 计算(64 位无符号整数)*(64 位无符号整数)除以 2^64 的商

java - 使用长数生成2个唯一的长数

c++ - | 有什么用(按位或运算符)在 setiosflags 的上下文中?

c++ - 如何在 C/C++ 中运行阿克曼函数而不出错?

javascript - 如何在 JavaScript 中设置、清除和切换单个位?

java - 为什么在 Java 中 (high + low)/2 是错误的,但 (high + low) >>> 1 不是?

c# - 为什么在 C# 中进行按位运算时必须强制转换为 0(零)?