Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如果不对浮点数进行任何操作,浮点数是否会失去精度_C#_Floating Point - Fatal编程技术网

C# 如果不对浮点数进行任何操作,浮点数是否会失去精度

C# 如果不对浮点数进行任何操作,浮点数是否会失去精度,c#,floating-point,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(va

我有这样一门课:

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
可以用十进制和二进制浮点完全准确地描述,因此它应该可以工作。其他值可能不是,您不应该(正如其他人所指出的)依赖
==
来获取浮点值


请参阅此处的详细信息:

您不应该将浮点数与“==”进行比较。相反,您可以使用边框。例如,您可以执行以下操作,而不是比较==0

float border = 0.00000001;
if( (val - border) <= 0 && (val + border) >= 0)
float border=0.00000001;
如果((值-边框)=0)

归根结底,在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位

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


是的,这看起来很愚蠢,但这些错误确实会增加。在某些地方不太重要,在其他地方错误工厂猖獗。

你永远不应该依赖于带浮点数的
=
,我认为只要你在做
t.CheckValue(0f)
它应该返回true,尽管
t.CheckValue(myFloat-myFloat)
可能不是那么简单。
使用相等运算符比较浮点数。舍入值时可能会丢失精度。
Resharper说。你认为它们会怎样?放射性衰变?这是来自ReSharper的一个奇怪提示,@StephenCanon我猜这是指在相等比较之前可能发生的事情?+1“使用不太可能有完美浮点表示的sin和cos值”,由于只能将函数
sin
cos
应用于本身以双精度表示的数字,因此
sin
cos
的所有结果都是近似值,除非它们应用于+0或-0。事实上,当以任何正常的二进制浮点格式使用默认舍入进行计算时,1.0/3*3正好是1.0,所以这是一个非常糟糕的示例。@Stephennon是的,它有点弱。。。但在概念上是合理的。当您在幕后或通过编写糟糕的代码切换精度时,会出现错误。例如(错误代码警告):
var a=1.0f/3;var b=a-(1.0/3)
a
是浮点,
b
是非零双精度。如果使用了足够的数字,则在十进制中描述某些浮点值不会有错误。也许您的意思是,当十进制值转换为二进制浮点值时,以及在执行算术运算时,可能会出现错误?