浮点序列化/解析舍入

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

我在内存中存储了以下浮点数(

float
,而不是
double

0b00111101111001000010000111001000

根据 floating-point-converter 转换为

0.111392557621002197265625

我将其序列化,向上舍入到第 9 位数字,并将其存储为以下字符串:

0.111392558

我明白,如果现在我解析字符串,我正在使用 stof,我应该期望一些精度损失,这意味着我不能保证解析的值会产生原始值,即

0.111392557621002197265625

事实是,我正在做一些单元测试,并且我始终发现我的期望从未达到,原始值和解析值始终相同。

我的期望正确吗?

c++ floating-point rounding
1个回答
0
投票

好吧,即使你提到的网站也显示了正在发生的事情 - 但看来你无法真正理解它。

重要的是浮点数是二进制的。在该网站中,在“十进制表示”中输入“0.5”,并观察下面的字段显示了很好的数字——没有错误,二进制值末尾有很多 0。

现在,输入“0.4”并观察其他数字如何变得一团糟。这是为什么?

0.5 是 1/2,或 2^-1——它是 2 的幂,这就是二进制值的含义:您需要能够将数字表示为此类二次幂数字的和。 2^-2 是 0.25,2^-3 是 0.125——无论你是否相信我,用这些数字你都无法精确地得到 0.4,因此工具显示出“混乱”。

要记住的重要一点是,数字的小数部分并不像您习惯的二进制那样工作。虽然十进制中的“1/3”产生具有无限十进制数字的数字,但二进制表示有更多这样的情况。

顺便说一句,这就是 COBOL 提供十进制数据类型的原因——它是用于业务计算的,并且您不能让货币计算得到与预期稍有不同的结果......

让我们从不同的方向来处理它:在工具中输入二进制值,并观察其转换为“0.11139256”。现在,在工具中输入您的另一个值“0.111392558”,并观察它产生完全相同的二进制值...您已经处于浮点数没有足够位来区分两者的范围内。因此,您提供的所有数字都会产生相同的二进制表示形式......因此它们都是相同的。

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