1

没有真正需要解决这个问题,我只是想知道为什么。让我们取两个数字:

#include <iostream>
using namespace std;

int main()
{
    unsigned long long int a = 17446744073709551615;
    signed long long int b = -30000000003;
    signed int c;
    c = a/b;
    cout << "\n\n\n" << c << endl;
}

现在,最近我得到的答案是零。我的 long long 的大小是 8 个字节,因此足以将它与无符号标签一起使用。C 变量也应该足够大以处理答案。(根据谷歌的说法,它应该是 -581 558 136)。所以...

编辑我想在我的机器上指出...

使用 numeric_limits,a 落在最大值 18446744073709551615 内,b 落在 -9223372036854775808 的最小值内。

4

2 回答 2

7

您发生了许多隐式转换,其中大多数是不必要的。

unsigned long long int a = 17446744073709551615;

无后缀十进制整数文字的类型为intlong intlong long int; 它永远不是无符号类型。long long int该特定值几乎肯定超过了 a (2 63 -1)的最大值。除非您的编译器具有比 64 位更宽的有符号整数类型,否则这会使您的程序格式错误。

添加ULL后缀以确保文字的类型正确:

unsigned long long int a = 17446744073709551615ULL;

该值恰好介于 2 63 -1 和 2 64 -1 之间,因此它适合 64 位无符号类型,但不适合 64 位有符号类型。

(实际上就U足够了,但明确一点也无妨。)

signed long long int b = -30000000003;

这应该不是问题。30000000003是某种有符号整数类型;如果您的编译器支持long long至少 64 位宽的 ,则不会溢出。不过,只要您需要在 的值上加上后缀,a明确说明就没有坏处:

signed long long int b = -30000000003LL;

现在我们有:

signed int c;
c = a/b;

将 a除以unsigned long longasigned long long会导致有符号操作数转换为unsigned long long。在这种情况下,被转换的值是负数,所以它被转换成一个大的正值。转换-30000000003unsigned long long收益率18446744043709551613。除以17446744073709551615产生18446744043709551613零。

除非您的编译器支持大于 64 位的整数(大多数不支持),否则您将无法直接除以17446744073709551615-30000000003获得数学上正确的答案,因为没有整数类型可以表示这两个值。所有算术运算符(除了移位运算符)都需要相同类型的操作数,并根据需要应用隐式转换。

在这种特殊情况下,您可以除以17446744073709551615ULL然后30000000003ULL占符号。(检查负整数除法的语言规则。)

如果你真的需要这样做,你可以求助于浮点(这意味着你可能会失去一些精度)或使用一些任意宽度的整数算术包,如GMP

于 2014-02-16T04:53:26.563 回答
0

b 被视为大于 a 的无符号数。因此,您得到的答案为 0。

尝试将其用作

c = abs(a) / abs (b)
if ((a < 0 && b > 0 ) || (a> 0 && b < 0))
   return -c;
return c;
于 2014-02-16T04:40:53.440 回答