如果不对浮点数进行运算,浮点数是否会失去精度
本文关键字:浮点数 是否 失去 精度 运算 如果不 | 更新日期: 2023-09-27 18:02:11
我有一个这样的类:
public class Test
{
public void CheckValue(float val)
{
if (val == 0f)
{
//Do something
}
}
}
//Somewhere else..
void SomeMethod
{
Test t = new Test();
t.CheckValue(0f);
}
是否保证检查if (val == 0f)
会返回true
?或者,当您使用浮点数执行运算时,浮点数只会失去精度吗?
它们不会丢失精度。用十进制来描述某些浮点值是不准确的。当对它们进行操作时,这些不准确的地方可能会相加或相互抵消。
在您的情况下,0
可以用十进制和二进制浮点完全准确地描述,因此它应该可以工作。其他值可能不是,您不应该(正如其他人所指出的(依赖==
来获取浮点值。
点击此处查看更多信息:http://floating-point-gui.de/
归根结底,在保存float
的32位内存中,你不能完美地表示每个浮点数(其无穷大的方差(。一个不能完美表示的数字只会有一个很小的误差值,但它会存在。
例如,在最近的浮点表示中,1/3(大致(为0.333333343267。你有7个小数位数的准确度,然后它碰到了一个小问题。假设你把1除以3,然后再乘以3。结果不是1,而是1.0000000298和变化。所以(1/3)*3 =/= 1
。
这些代表性错误就是为什么直接比较浮点值被认为是不好的做法。
在需要将这些小错误的影响降至最低的情况下,你应该尽你所能阻止它们的积累。例如,一次旋转一组坐标会产生不完美的结果,因为每次旋转操作(使用不太可能具有完美浮点表示的sin
和cos
值(引入的误差会随着时间的推移而累积。最好跟踪总的角度变化,每次旋转原始矢量以获得较小的误差值。
另一个可以咬你的地方是for
循环。如果要以每步1/30000的速度执行10000步,请使用int作为循环变量,并将当前位置计算为除法。速度较慢,是的,但要准确得多。使用浮点运算,您的错误会累积,直到您只有大约3个可靠的有效小数位数,而不是每次除法时超过7。
速度不错,但在某些情况下精度更好。
是的,这看起来很愚蠢,但这些错误确实会越来越多。在某些地方不那么重要,在另一些地方则是猖獗的错误工厂。
您永远不应该将浮点数字与"=="进行比较。相反,您可以使用边界。例如,你可以做一些类似的事情,而不是比较==0
float border = 0.00000001;
if( (val - border) <= 0 && (val + border) >= 0)