c++ - 为什么 double 可以存储比 unsigned long long 更大的数字?

标签 c++ c floating-point precision floating-point-conversion

问题是,我不太明白为什么 double 可以存储比 unsigned long long 更大的数字。由于它们都是 8 字节长,所以 64 位。

在 unsigned long long 中,所有 64 位都用于存储值,另一方面,double 有 1 表示符号,11 表示指数,52 表示尾数。即使使用 52 位(用于尾数)来存储没有浮点的十进制数,它仍然是 63 位 ...

但是 LLONG_MAX 明显小于 DBL_MAX ...

为什么?

最佳答案

原因是 unsigned long long 将存储 exact 整数,而 double 存储尾数(有限的 52 位精度)和指数。

这允许 double 存储非常大的数字(大约 10308),但不精确。 double 中有大约 15 个(几乎 16 个)有效小数位,其余 308 个可能的小数位为零(实际上未定义,但您可以假设“零”以便更好地理解)。
unsigned long long 只有 19 位,但每一位都是精确定义的。

编辑:
在回复下面的评论“这到底是如何工作的”时,您有 1 位用于符号,11 位用于指数,52 位用于尾数。尾数在开头有一个隐含的“1”位,它没有被存储,所以实际上你有 53 个尾数位。 253 是 9.007E15,所以你有 15 个,几乎 16 个十进制数字可以使用。
指数有一个符号位,范围从 -1022 到 +1023,用于缩放(二进制左移或右移)尾数(21023 约为 10307,因此范围有限制),因此非常小的和非常大的数字同样可能使用这种格式。
但是,当然,您可以表示的所有数字都只有与 matissa 匹配的精度。

总而言之, float 不是很直观,因为“简单”的十进制数根本不一定可以表示为 float 。这是因为尾数是二进制的。例如,可以(并且很容易)以完美的精度表示任何高达几十亿的正整数,或像 0.5、0.25 或 0.0125 这样的数字。
另一方面,也可以表示像 10250 这样的数字,但只是近似的。其实你会发现10250和10250+1是同一个数(等等,什么???)。这是因为尽管您可以轻松拥有 250 位数字,但您没有那么多重要 数字(将“重要”读作“已知”或“已定义”)。
此外,即使 0.3 甚至不是一个“大”数字,也只能近似地表示像 0.3 这样看似简单的东西。但是,你不能用二进制表示 0.3,而且无论你附加什么二进制指数,你都不会找到任何导致 0.3 的二进制数(但你可以非常接近)。

一些“特殊值”是为“无穷大”(正数和负数)以及“非数字”保留的,因此您的值小于总理论范围。 p> 另一方面,

unsigned long long 不会以任何方式解释位模式。您可以表示的所有数字只是位模式表示的确切数字。每个数字的每个数字都是精确定义的,不会发生缩放。

关于c++ - 为什么 double 可以存储比 unsigned long long 更大的数字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30052710/

相关文章:

c - 未定义的对 memcpy_s 的引用

c - 将地址作为符号加载到通用寄存器中

C++浮点减法似乎没有发生

opencv - 将 Mat 对象的类型从 CV_32F 更改为 CV_8U

c++ - 使用 std::vector <mutex*> 调用 std::lock ()

c++ - 未在范围内声明 - priority_queue C++ 的友元比较器类

c - 优化一个c函数去掉compare

c++ - 什么决定了 C 中整数的大小?

C++复制指定字符串索引之间的任何子字符串

c - 如何将asin结果保存在短变量中?