我知道关于浮点数有很多问题,但是我仍然找不到我想要的东西。
将1 000 000 032
转换为浮点数是0 10011100 11011100110101100101000
,实际存储在浮点数中的值是1.0E9
,我知道为什么会这样。但是当我使用FloatConverter转换1 000 000 033
时。实际存储在浮点数中的值为1 000 000 064
。为什么会这样呢?由于1 000 000 032
的23个最高有效数字与1 000 000 033
答案 0 :(得分:2)
单精度浮点数包含23个有效位,而不是有效十进制数字。
要知道这些值如何取整,以二进制形式编写时会更容易看到它们:
₁₂₃₄₅₆₇₈₉₀¹²³⁴⁵⁶⁷⁸⁹⁰₁₂₃₄₅₆₇₈₉₀
1000000000 = 111011100110101100101000000000 (0x4e6e6b28)
1000000032 = 111011100110101100101000100000
1000000033 = 111011100110101100101000100001
1000000064 = 111011100110101100101001000000 (0x4e6e6b29)
Truncated ^^^^^^
Normalized: 1.11011100110101100101000 x 2²⁹
当指数为29时,这些值的闭包表示为1000000000和1000000064,它们分别以单精度存储为0x4e6e6b28
和0x4e6e6b29
。如您所见,它们在最后一个位置仅相差一小部分
因此,当我们将1000000032和1000000033转换为有效的24位时,首先将截断最后6位,然后再应用适当的舍入。对于1000000033,很容易看到它比前一个(1 000 000 064
)更接近下一个可表示的值(1 000 000 000
),因此当然会四舍五入。但是1000000032恰好在这些值之间,因此取决于实现选择IEEE-754标准指定的允许舍入模式之一:
该标准定义了五个取整规则。前两个规则四舍五入到最接近的值;其他被称为有向四舍五入:
舍入到最接近的
- 四舍五入至最接近的值,四舍五入至最接近的值;如果该数字落在中间,则用偶数(零)最低有效位四舍五入到最接近的值; 这是二进制浮点的默认值,建议使用十进制的默认值。
- 四舍五入到最接近的值,从零开始舍入-四舍五入到最接近的值;如果该数字落在中间,则四舍五入为大于(对于正数)或小于(对于负数)的最接近值;用作十进制浮点数的选项。
似乎在这里使用了推荐的平整关系规则。同样,由于与偶数的联系规则
,将1000000096舍入为1000000128。您可以查看Error due to conversion
字段,对于1000000032、1000000033和1000000096,错误分别为-32、31和32
您还可以尝试使用Exploring Binary's converter,它提供了更多有用的表示形式,并清楚说明了其舍入值的方式
这是一个十进制到二进制浮点转换器。它将使用从一半到偶数舍入(默认的IEEE舍入模式),将十进制数转换为最接近的单精度和双精度IEEE 754二进制浮点数。它使用任意精度算法实现,因此其转换正确舍入。它将转换普通数和次普通数,并将转换为溢出(无限)或下溢(零)的数字。
答案 1 :(得分:1)
不要假定所显示的是用十进制表示该显示时所存储的内容。在显示十进制值中,您将从二进制转换为十进制,并引入舍入以及所选的任何显示方式的表示规则-是某些库函数还是调试器。
例如,fprintf%f格式说明符默认情况下仅考虑6个有效十进制数字。
这就是说1.0e9最有可能是显示的,而不是存储的内容。