64位无符号整数有多大?

时间:2017-09-27 07:57:16

标签: c

我很清楚How big can a 64bit signed integer be? 感谢这个问题及其直截了当的答案。

那么,根据这个,我可以说unsigned int可以是2 ^ 64 - 1而不是2 ^ 63 - 1吗?

2^63 - 1:    0111111111111111111111111111111111111111111111111111111111111111

2^64 - 1:    1111111111111111111111111111111111111111111111111111111111111111

当且仅当我正确使用它时,如何检测无符号溢出?以二进制补码表示的有符号整数溢出将侵入最高位位置,返回负数。但是这个未签名的案件怎么样?

6 个答案:

答案 0 :(得分:5)

有符号整数只能达到2^63-1(9,223,372,036,854,775,807),因为最重要的位是为符号保留的。如果此位为1,则该数字为负数,并且可以低至-2^63( - 9,223,372,036,854,775,808)。

在带符号的64位整数上,2^64-1实际上是数字-1

但是,如果使用无符号整数,则值从0开始,2^64-1(18,446,744,073,709,551,615)成为它的最高值,但无符号整数不能表示负值。

答案 1 :(得分:3)

64位有多大?

答案是一个无符号64位整数有多大的问题,我建议在汇编或任何支持64位数据类型的编程语言中做一个小的比较测试。

从0到最大值的计数,可以存储在变量中。第一次使用32位宽变量,第二次使用64位宽变量。尝试估计结果。

在C#中,对于32位变量,代码可能看起来像这样(...请忽略一个问题):

for (uint i = 0; i < uint.MaxValue; i++)
{
    Process(i);
}

uint.MaxValue是将变量的所有位设置为1时获得的数字。它基本上等于2 ^ 32 - 1 = 4294967295.这大约是42亿。

具有64位变量的案例的测试代码类似:

for (ulong i = 0; i < ulong.MaxValue; i++)
{
    Process(i);
}

ulong.MaxValue这次是2 ^ 64 - 1 = 18446744073709551615(一个20位数字)。

大约10亿次Process()操作/秒,第一个程序将完成其工作:

2 ^ 32/1000000000 = 4.29秒

以相同的处理速度,第二个程序将完成其工作:

2 ^ 64/1000000000 / 3600/24/365 = 585年!

这是一个很大的区别!谁有时间等待585年才能完成基本工作!

有趣的是,每秒10亿次操作非常激进!对于一个更加逼真的场景,你每秒执行100万到几亿次操作,时间会爆发到数千甚至数十万年来单独执行!

对于大多数人来说,上述练习是64位电源的有趣可视化。但是,这个练习也展示了使用算法的计算机科学工程师所面临的现实。采用蛮力方法的执行不当的算法(例如搜索或计算问题)可能会破坏您的软件。

其他大数字

作为回顾,请记住,存储在64位寄存器/变量中的最大数量是2 ^ 64 - 1 = 18446744073709551615(一个20位数字)。虽然这个数字看起来很大,但是比较例如1 googol是10 ^ 100(1后跟100个零)!

即使是大的googol也不到70岁! (70因子,即1 * 2 * ...... * 70)。哇!这真的显示了乘法的力量!

你知道吗:googol完全在双数据类型(IEEE 754浮点)的范围内 - 也是64位结构。在将来的文章中将介绍如何双重存储如此大的数字。

我希望你玩得开心!

答案 2 :(得分:2)

通过查看值很难或无法检测到 问题是最大值加上甚至只有1仍然/再次是有效值;即0。

这就是为什么大多数程序员尽可能避免,如果它实际上是一个错误的值。对于某些应用程序,环绕是逻辑的一部分并且很好。

如果您计算,例如c=a+b;(a,b,c为64位无符号整数和a,b令人担忧地接近最大值,或者是偏移量)并且想要查明结果是否受到影响,
然后检查((max - b) < a); max是编译器提供的适当符号。

不要将自己的最大值计算为2 ^ 64-1,它将是特定于实现和平台特定的。最重要的是,它将包含两次环绕(2 ^ 64超出最大值,可能为0;并且减去1经过0返回......)。即使^被理解为“对权力”的适当版本,这也适用。

答案 3 :(得分:2)

您对有符号和无符号整数的最大大小的假设是正确的。签名的实际值为9223372036854775807,未签名的实际值为18446744073709551615。

检测无符号加法的溢出非常简单 - 如果结果小于任一操作数,则会出现溢出。

减法类似,如果结果大于第一个操作数,则表示溢出。

乘法很难,我不知道一个简单的规则。

除非你除以零,否则溢出是不可能的。

答案 4 :(得分:2)

可以是18446744073709551615

18,446,744,073,709,551,615
q5 q4  t   b   m   t   h

答案 5 :(得分:1)

  

64位无符号整数有多大?

要编码最大值,最好使用UINT64_MAX。当64位类型可用时,它总是被定义。

#include <stdint.h>
#define MAX64BIT UINT64_MAX 
or 
#define MAX64BIT 0xFFFFFFFFFFFFFFFF
or
#define MAX64BIT 18446744073709551615u
  

如何检测无符号溢出?

使用N位无符号类型:uintN_t a,b;

溢出检测:

// addition
uintN_t sum = a + b;
bool overflow = sum < a;  // or sum < b

// subtraction
bool overflow = b > a;
uintN_t diff = a - b;  //

由于带符号数学的未定义行为(UB),签名类型需要其他代码。 Example