提问人:user1234567 提问时间:7/11/2020 最后编辑:user1234567 更新时间:7/14/2020 访问量:237
浮点戏剧性误差(小数部分完全丢失)
Floating point dramatic error (fractional part is completely lost)
问:
quotient = 43156414f / 3;
我在这里得到了 == 14385472(完全不是真正的值:14385471,333......它完全失去了所有部分!quotient
我知道浮点计算不准确(似乎,不是全部,我应该知道),但是,正如我所告知的,错误可能出现在更远的有效数字上。但这里的股息只有 8 位数字。为什么会发生如此戏剧性的错误?
可选子问题:我应该记住哪些规则来预见将来的此类错误?
请注意:将除数类型从浮点数更改为双倍数可以解决此问题。
答:
float 的精度为 6-9 位。您的价值太大,无法在不损失的情况下放入浮点数。
double 的精度约为 15-17 位。
举例来说,检查 or 的值 - 它们都43156416(int)43156414f
(double)43156414f
评论
浮点
精度描述为 6-9 位没有任何意义。
好吧,() 使用 23 位作为尾数float
Single
https://en.wikipedia.org/wiki/Single-precision_floating-point_format
所以可以表示接近的整数。
我们拥有的可能性是:float
2**24 - 1 == 16777215
14385471
01001011 01011011 10000001 00111111 correponds to 14385471f (let's add 1 bit)
01001011 01011011 10000001 01000000 correponds to 14385472f
因此,正如我们所看到的,我们只有和可供选择;在.
让我们来看看14385471f
14385472f
14385471.33333f
floate
float x = 14385471.3333333333f;
byte[] data = BitConverter.GetBytes(x);
Console.Write(" ", string.Join(" ", data
.Reverse()
.Select(b => Convert.ToString(b, 2).PadLeft(8, '0'))));
我们将有
01001011 01011011 10000001 00111111
对应于 .我们还有更多问题14385471f
quotient = 43156414f / 3;
现在,不能表示为 but43156414f > 2**24 - 1 (16777215)
43156414f
float
01001100 00100100 10100000 11110000 corresponds to 43156416
所以实际值是quotient
43156416 / 3 == 14385472
最后,如果想要拥有,还不够,试试:14385471.33
Single
double
// 14385471.333333334
double quotient = 43156414d / 3;
下一个:如何全精度打印浮点数
评论