unsigned long long不会存储大数字

时间:2013-03-10 21:23:57

标签: c++

我对C / C ++ unsigned long long类型感到困惑,因为理论上它应该存储最多2 ^ 64-1,这是一个19位十进制数字,但是代码如下:

unsigned int x = 1000000u; //(One million)
unsigned long long k = (x*x);
cout << k << endl;

打印出3567587328,这是不正确的。 现在1,000,000 ^ 2导致1,000,000,000,000 - 一个12位十进制数字,远低于偶数signed long long的限制。怎么会发生这种情况? 它与我正在运行的系统有什么关系吗? (32位Ubuntu)

如果我需要64位系统来实现64位操作,那么会出现另一个问题: 大多数编译器使用线性同余生成器生成随机数,如下所示:

x(t) = (a*x(t-1) + c) mod m.

ac通常是32位大号,m是2^32-1 因此,a*x(t-1)很可能在执行模运算之前产生64位数。

如果需要64位系统,那么自20世纪90年代以来gcc如何在16-32位机器上生成随机数?

万分感谢。

3 个答案:

答案 0 :(得分:10)

当然kunsigned long long,但xunsigned int,因此x*x也是如此。您的表达式计算为unsigned int,当超过无符号类型的限制时,会导致通常的回绕。损坏完成后,它将转换为unsigned long long

可能的修复:

  • 使x成为unsigned long long
  • unsigned long long k = ((unsigned long long)x*(unsigned long long)x);
  • unsigned long long k = (1ULL*x*x);

答案 1 :(得分:4)

xunsigned int - &gt; x*x也是unsigned int。如果乘法的结果超过unsigned int的最大值,则发生环绕。 仅在这些操作之后,结果才会被分配到接收变量(k)中。如果您希望结果为unsigned long long,则需要将至少一个操作数提升为此类型,例如:unsigned long long k = (unsigned long long)x * x;

关于你的第二个问题:编译器通常不生成数字,这是在运行时完成的。我不知道你在哪里得到公式x(t) = (a*x(t-1) + c) mod m。假设这确实是公式,那么有方法可以保持中间结果的界限:模运算可以应用于任何操作数或中间结果而不会改变结果。因此x(t) = (a*x(t-1) + c) mod m = (a mod m) * (x(t-1) mod m) + c mod m

答案 2 :(得分:3)

当您将unsigned int乘以右侧的unsigned int时,结果为unsigned int。因此,它与两个数字相乘的限制相同,无论此值随后被分配给unsigned long long这一事实。

但是,如果您将unsigned int变量转换为unsigned long long,则结果将为unsigned long long,并且该值不会限制为unsigned int的大小。

unsigned long long k = (((unsigned long long)x)*((unsigned long long)x));

这应该会给你你想要的结果。