仅使用按位转换long和int

我试图仅使用按位运算符重现以下函数的输出! 〜&^ | + >。

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;
}

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

mafanmafan_elsa 回答:仅使用按位转换long和int

以下测试为您的函数返回0

#include <stdio.h>
#include <limits.h>

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

int main() {
    printf("%d",test_dl2(INT_MAX,1));
    return 0;
}

我使用的数字是导致溢出的int的最大值。您的代码用于测试int中的溢出,因此您需要使用引起+的{​​{1}}中溢出的值进行测试。有很多测试表明这种溢出,而我只是一个例子。

更新

如注释中所述,int属于lsum == (int) lsum中定义的实现中的代码部分,因此您根本无法传递函数结果。如果数据类型是无符号的(Cunsigned int),我的观点是正确的。此代码也是在unsigned long long中的C++20之前定义的实现。在C++之后,它再次在C++20中定义。

,

也许您正在尝试检查添加 x y 是否会给出uint32_t的有效结果。正如评论中已经指出的那样,问题在于,如果数字太大,则从uint64_t到uint32_t的转换是不确定的。

目前C和C ++都没有假设数字表示为二进制补码,因此很难进行这种验证。这将改变,因为下一个C ++标准将强制使用two's complement to code signed integers(并且可能会遵循C标准)。

但这不会表示错误的转换,并且您的代码仍然无效。

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

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

该方法的概述是:

  • 左移数字将它们除以2(假设带符号的左移是算术运算,在大多数计算机上都是如此,但标准目前尚无此要求)

  • 添加它们。这将计算 x / 2 + y / 2 ,并且等于(x + y)/ 2 ,除非,如果两个LSB均 x 和 y 是1,在这种情况下, x + y 中会产生一个权重为2 ^ 1的进位。
    我们通过 x y 的最低有效位(LSB)来测试此进位的存在,并将其加到和中。

  • 上一个计算(x + y)/ 2 的结果始终对32位有效。我们检查31位是否有效。如果为true, 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) ) ;
}
,

如果x + y大于tmax或小于tmin,则应返回0。

否则它将返回1。

本文链接:https://www.f2er.com/3168882.html

大家都在问