如何用C程序显示最大的unsigned long long值?为何下述程序未能正确输出2^64-1的整数值?
嘿,咱们来逐个解决你的问题:
1. 如何编写C程序以显示unsigned long long类型的最大可能取值?
有几种简单又可靠的方法:
方法一:用标准库宏(最推荐)
C标准库的<stdint.h>头文件里定义了ULLONG_MAX宏,直接拿来用就行,这是编译器提供的准确值:#include <stdio.h> #include <stdint.h> int main(void) { printf("%llu\n", ULLONG_MAX); return 0; }方法二:利用无符号整数的溢出特性
无符号整数的取值是模运算规则,当你给unsigned long long赋值-1时,会自动溢出到该类型的最大值(所有位全为1):#include <stdio.h> int main(void) { printf("%llu\n", (unsigned long long)-1); return 0; }方法三:位运算构造
直接构造一个所有位都是1的unsigned long long值:#include <stdio.h> int main(void) { printf("%llu\n", ~0ULL); return 0; }这里
0ULL是unsigned long long类型的0,取反后所有位就变成1了,正好是该类型的最大值。
2. 你的pow()程序为什么输出不符合预期?
问题核心在于浮点数的精度限制:
pow()是浮点数函数,返回的是double类型的值。而double的有效精度只有大约53位(尾数部分是52位+1位隐藏位)。当你计算pow(2, 64)时,虽然2的整数次幂在double里可以精确表示到2^1023,但执行pow(2,64) - 1时就出问题了:264和264-1之间的差值,小于double能区分的最小精度单位(ULP,最后一位的单位),所以double无法精确表示264-1这个数,计算结果会被近似成264。
接下来你把这个近似后的double值强制转换成unsigned long long,但unsigned long long的最大值是264-1,264已经超出了它的取值范围。根据C标准,无符号整数的溢出转换是取模264,所以最终结果就变成了0,完全不符合预期的264-1。
修复方案
把浮点数运算换成整数运算就行,比如用前面提到的任意一种方法:
#include <stdio.h> #include <stdint.h> int main(void) { printf("%llu\n", ULLONG_MAX); // 或者用 (unsigned long long)-1,或者 ~0ULL return 0; }
内容的提问来源于stack exchange,提问作者Marcos Gonzalez

