仅按位铸造long和int型

问题描述 投票:0回答:3

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

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

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

c bit-manipulation bitwise-operators
3个回答
1
投票

以下测试为您的函数返回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中的溢出,因此您需要使用导致+int溢出的值对其进行测试。有很多测试表明这种溢出,而我只是一个例子。

更新:

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


1
投票

也许您正在尝试检查xy的加法是否将作为uint32_t提供有效的结果。正如评论中已经指出的,问题是,如果数字太大,则从uint64_t到uint32_t的转换是不确定的。

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

但是这并不意味着错误的转换,您的代码仍然无效。

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

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

该方法的概述是:

  • 左移数字将它们除以二(假定带符号的左移是算术运算,在大多数计算机上是正确的,但标准目前尚无此要求。]]

  • 添加它们。如果x

    y]的LSB都等于(x + y / 2)>,则等于(x + y / 2)] >是1,在这种情况下,x + y
  • 中的权重为2 ^ 1。我们通过 xy的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。

0
投票
否则它将返回1。
© www.soinside.com 2019 - 2024. All rights reserved.