使用不同的表达式计算同一整数时的结果不一致

Non consistent results when calculating the same integer with different expressions

本文关键字:整数 不一致 结果 表达式 计算      更新时间:2023-10-16

同一表达式的算术结果会导致不同的结果,具体取决于我在一行中定义整数或使用几个步骤:

int main() {
    unsigned long long veryBigIntOneLine = ((255*256+255)*256+255)*256+255;
    unsigned long long veryBigInt = 255;
    veryBigInt *= 256;
    veryBigInt += 255;
    veryBigInt *= 256;
    veryBigInt += 255;
    veryBigInt *= 256;
    veryBigInt += 255;
    unsigned long long veryBigIntParanthesis = (((((255*256)+255)*256)+255)*256)+255;
    unsigned long long fourthInt = 256;
    fourthInt *= 256;
    fourthInt *= 256;
    fourthInt *= 256;
    --fourthInt;
    cout << "veryBigIntOneLine: " << veryBigIntOneLine << endl;
    cout << "veryBigInt: " << veryBigInt << endl;
    cout << "veryBigIntParanthesis: " << veryBigIntParanthesis << endl;
    cout << "fourthInt: " << fourthInt << endl;
    return 0;
}

它们都应该描述相同的数字,256^4-1(或2^32-1(,但结果是不同的。

veryBigIntOneLine: 18446744073709551615
veryBigInt: 4294967295
veryBigIntParanthesis: 18446744073709551615
fourthInt: 4294967295

4294967295是预期的答案(因为它是由谷歌计算器为所有四个表达式给出的(。

此外,18446744073709551615可能不是计算结果的确切结果,因为我在编译时收到两个单行表达式的溢出警告(即使我尝试使用 __int128 类型(。它实际上是 2^64-1,这是我的编译器的无符号长长的最大值(veryBigIntOneLine+1 给出 0(。

初始化

代码((255*256+255)*256+255)*256+255遭受有符号整数溢出(未定义行为(以及有符号int到无符号的隐式转换。虽然分步计算避免了这些问题,但右手操作数被隐式转换为无符号长整型。

只需使用适当的文字即可解决这些问题:

unsigned long long veryBigIntOneLine{ ((255ull*256ull+255ull)*256ull+255ull)*256ull+255ull}; // 4294967295
这是因为

您没有使用unsigned long long文字。如果您希望文本与您的定义匹配,则需要使用:

255ULL + 256ULL * 255ULL + ...

如果创建 64 位的数字,则ULL非常重要。在 C 中,没有后缀的数字可能是 64、32 甚至只有 16 位(甚至某些 CRAY 上的字节为 64 位。这也意味着您的代码可以在其中一个 CRAY 系统上找到。