提问人: 提问时间:10/8/2022 更新时间:4/22/2023 访问量:410
避免浮点数舍入不精确
Avoiding float rounding imprecision
问:
在用浮点数进行除法时,我经常会遇到不精确的情况(例如,等)。5.000000001
有没有办法在使用浮点数时不出现浮点不精确问题? 也许有更好的选择可以避免它?
提前感谢您的所有回答!
答:
-2赞
Guillaume Brunerie
10/8/2022
#1
你找不到这样的“不精确”,即使你可以,你也无法修复它们。例如,根本没有办法将 0.1 精确地表示为浮点数。这不是一个错误,它只是浮点数的工作方式(在任何语言中),你只需要解决它。
以下是一些解决方法:
- 仅使用整数,因为它们不会受到舍入误差的影响(只要它们不是太大)。例如,如果您想处理小数点后只有两位数字的财务金额,您应该以美分存储您的金额,而不是以欧元/美元/...存储,以便只处理整数。
- 如果你想使用任意分数,你应该使用一个专门为此设计的库。肯定有很多这样的库。或者你可以编写自己的,其中分数 a/b 表示为 (where 和 是整数,所以没有舍入错误),然后你在这个表示上实现加法、乘法、相等等,只负责操作整数。
{numerator: a, denominator: b}
a
b
- 如果您需要使用任意浮点数(例如,您正在编写一个检测两个移动形状碰撞的函数),只需记住永远不要使用相等。对于任意浮点数来说,相等是毫无意义的。您可以改用类似 where is selected of a way to a fit your application 的方式。
Math.abs(b - a) < epsilon
epsilon
评论
1赞
Eric Postpischil
10/8/2022
回复“只使用整数,因为它们不会受到四舍五入误差的影响(只要它们不是太大)”:2014 年 6 月 6 日,苹果股票的收盘价为每股 64557 美分。整数算术计算出拆分调整后的价格为每股 9222 美分,但目前的答案约为每股 9222.428571 美分。整数算术可能会出现舍入误差。
0赞
Eric Postpischil
10/8/2022
Re “对于任意浮点数来说,相等是毫无意义的”:人们通常不会计算任意浮点数;他们计算对其目的有意义的数字。在浮点运算中,没有适度量级导数的函数(包括检验相等性,因为它是不连续的)确实很难处理,但说它们总是毫无意义是不正确的。例如,测试函数参数是否处于奇点可能很有意义。
0赞
Guillaume Brunerie
10/8/2022
“但目前的答案是每股约9222.428571美分。整数算术会受到四舍五入误差的影响。我不知道你在说什么,9222.428571 不是整数,所以你不是在做整数算术。
0赞
Guillaume Brunerie
10/8/2022
“人们通常不会计算任意浮点数”他们绝对会这样做。例如,如果您使用 requestAnimationFrame 来计算动画,则从上一帧到当前帧的时间是任意浮点数,因此您从中计算的所有内容也将是(除非您四舍五入,但没有理由,任意浮点数都可以)。
0赞
Guillaume Brunerie
10/8/2022
“例如,测试函数参数是否处于奇点可能是有意义的。我完全不相信这一点。例如,如果您不想除以 0,您可能也不想除以 0.1+0.2-0.3,即使它不等于 0。
评论
.0
2.99999
2.0 + 0.99999
6.0 / 2.0