在 C 中,为什么我不能将 pow(2,64) 转换为 unsigned long?

问题描述 投票:0回答:1

我正在尝试打印 C 中无符号长整型的最大值(在我的机器上为 18446744073709551615),而不使用 limit.h 中的值,也不使用按位运算符(来自 K&R 的练习 2-1,仅使用在预订截止日期)。显然只是作为练习,不适用于任何现实世界的应用。 我的想法(适用于所有其他数据类型)是

printf("Unsigned long: Max: %lu\n", (unsigned long)(pow(2,sizeof(unsigned long)*8)-1));

但由于某种原因,将 (pow(2,64)-1) 的输出转换为 unsigned long 显示为 2^63,即使 unsigned long 足够大以显示 pow(2,64)-1

我已经尝试过了

printf("Unsigned long: Max: %lu\n", ULONG_MAX); // works
printf("Unsigned long: Max: %lu\n", 2*(unsigned long)pow(2,63)-1); // works
printf("Unsigned long: Max: %.0f\n", pow(2,64)-1); // sort of works, but displays 18446744073709551616, i.e., 2^64 instead of 2^64-1
printf("Unsigned long: Max: %lu\n", (unsigned long)(pow(2,sizeof(unsigned long)*8)-1)); // does not work
printf("Unsigned long: Max: %lu\n", (unsigned long)pow(2,64)-1); //does not work

我不明白为什么最后两个选项不起作用。 感谢您的帮助!

c casting limit
1个回答
0
投票

获取无符号类型最大值的一个简单方法是使用

-1
:

    printf("%lu", (unsigned long)-1);

为什么

(unsigned long)(pow(2,sizeof(unsigned long)*8)-1)
在您的系统上导致
2^63
(我无法在我的系统上重现)的解释可能是您的系统实现
double
类型的方式。你说这是一个 32 位类型,这意味着它不是广泛使用的 IEEE 754 双精度类型。

关于浮点数如何存储,有几个很好的解释,所以我不再重复。参见例如c 中浮点的精确表示。

您的

double

 类型似乎无法表示 2^64,因此使用值 2^63 作为其最大值或“无穷大”的某种表示(即数字太大而无法表示)。减 1 不会改变该值,因为 
double
 类型无法表示这样的精度(由于它是 32 位类型,理论上只能表示 2^32 个不同的值,而 64 位 unsigned long 类型可以表示 2^64不同的值)。

© www.soinside.com 2019 - 2024. All rights reserved.