为什么我不能将一个大数字除以负数C ++

时间:2014-02-16 04:35:45

标签: c++ largenumber unsigned-long-long-int

没有必要解决这个问题,我只想知道原因。 我们来两个数字:

#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的最小值范围内。

2 个答案:

答案 0 :(得分:6)

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

unsigned long long int a = 17446744073709551615;

未填充的十进制整数文字的类型为intlong intlong 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;