我很清楚How big can a 64bit signed integer be? 感谢这个问题及其直截了当的答案。
那么,根据这个,我可以说unsigned int
可以是2 ^ 64 - 1而不是2 ^ 63 - 1吗?
2^63 - 1: 0111111111111111111111111111111111111111111111111111111111111111
2^64 - 1: 1111111111111111111111111111111111111111111111111111111111111111
当且仅当我正确使用它时,如何检测无符号溢出?以二进制补码表示的有符号整数溢出将侵入最高位位置,返回负数。但是这个未签名的案件怎么样?
答案 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位数据类型的编程语言中做一个小的比较测试。
从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)
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