没有必要解决这个问题,我只想知道原因。 我们来两个数字:
#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个字节,因此使用unsigned标签就足够了。 C变量也应足够大以处理答案。 (根据谷歌的说法,它应该是-581 558 136)。所以......
编辑我想在我的机器上指出......
使用numeric_limits a,最大值为18446744073709551615,且b落在-9223372036854775808的最小值范围内。
答案 0 :(得分:6)
您发生了许多隐式转化,其中大多数都是不必要的。
unsigned long long int a = 17446744073709551615;
未填充的十进制整数文字的类型为int
,long int
或long long int
;它永远不会是无符号类型。该特定值几乎肯定超过long long int
的最大值(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;
将unsigned long long
除以signed long long
会导致已签名的操作数转换为unsigned long long
。在这种情况下,转换的值是负数,因此它被转换为大的正值。将-30000000003
转换为unsigned long long
会产生18446744043709551613
。将17446744073709551615
除以18446744043709551613
会产生零。
除非您的编译器支持大于64位的整数(大多数都没有),否则您将无法直接除17446744073709551615
-30000000003
之外的数据并获得数学正确答案,因为没有可以表示两个值的整数类型。所有算术运算符(移位运算符除外)都需要相同类型的操作数,并根据需要应用隐式转换。
在这种特殊情况下,您可以将17446744073709551615ULL
除以30000000003ULL
,然后考虑该符号。 (检查负整数除法的语言规则。)
如果你真的需要这样做,你可以求助于浮点(这意味着你可能会失去一些精度)或者使用像GMP这样的任意宽度整数算术包。
答案 1 :(得分:0)
b被视为无符号数,大于a。因此,您得到的答案为0。
尝试将其用作
c = abs(a) / abs (b)
if ((a < 0 && b > 0 ) || (a> 0 && b < 0))
return -c;
return c;