如果没有对它们进行任何操作,浮点数是否会失去精度

时间:2013-03-05 10:20:22

标签: c# floating-point

我有一个类似的课程:

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吗?或者,当您使用它们执行操作时,浮点数是否会失去精度?

3 个答案:

答案 0 :(得分:4)

它们不会失去精确度。以十进制描述某些浮点值存在不准确之处。对它们进行操作时,这些不准确性可能会相互叠加或相互抵消。

在你的情况下,0可以用十进制和二进制浮点完全准确地描述,所以它应该有效。其他值可能不是,您应该(正如其他人指出的那样)不依赖于==来获取浮点值。

在此处查看更多信息:http://floating-point-gui.de/

答案 1 :(得分:1)

归结为你不能完美地表示持有float的32位内存中的每个浮点数(在所有无限方差中)。一个无法完美表示的数字只会有一个非常小的误差值,但它会存在。

例如,在最近的浮点表示中,1/3是(大致)0.333333343267。你有7个十进制数字的准确度,然后它会遇到一些障碍。所以假设你将1除以3​​,然后再乘以3.结果不是1,它是1.0000000298并且改变。所以(1/3)*3 =/= 1

这些表征性错误是直接比较浮点值被认为是不良实践的原因。

在您需要尽量减少这些小错误的影响的情况下,您应该尽一切可能阻止它们累积。例如,一次旋转一组坐标会给您带来不完美的结果,因为每次旋转操作引入的错误(使用sincos值不太可能具有完美的浮动表示)随着时间的推移积累。最好跟踪总角度变化并每次旋转原始矢量以获得更小的误差值。

另一个可以咬你的地方是for循环。如果要以每步1/30000执行10,000步,请对循环变量使用int并将当前位置计算为除法。更慢,是的,但更准确。使用浮点数会累积错误,直到您只有大约3个可靠的有效十进制数字,而不是每次划分时超过7。

速度很好,但在某些情况下精度更高。

是的,这似乎很愚蠢,但这些错误确实可以增加。在某些地方不那么重要,在其他地方猖獗的错误工厂。

答案 2 :(得分:-2)

永远不要将浮点数与“==”进行比较。相反,你可以使用边框。例如,您可以执行类似

的操作,而不是比较== 0
float border = 0.00000001;
if( (val - border) <= 0 && (val + border) >= 0)