C# 具有相同输入的浮点错误

C# 具有相同输入的浮点错误,c#,.net,floating-point,C#,.net,Floating Point,这有点奇怪。我在不同的时间为同一位代码的同一输入获得不同的输出 这是一个非常简单的计算,在一个处理指南针类型的类中,只需获得给定角度的弧度(以度为单位)。 事情是这样开始的: public double Radians { get { return this.heading_degrees * Math.PI / 180; } set { this.heading_degrees = valu

这有点奇怪。我在不同的时间为同一位代码的同一输入获得不同的输出

这是一个非常简单的计算,在一个处理指南针类型的类中,只需获得给定角度的弧度(以度为单位)。 事情是这样开始的:

public double Radians  
{  
    get   
    {  
        return this.heading_degrees * Math.PI / 180;  
    }  
    set  
    {  
       this.heading_degrees = value * 180 / Math.PI;  
       normalize();  
    }  
}  
(航向度是指南针类中的成员变量)
看起来还好吧?
除了我在“获取”给定角度的弧度时得到的结果不同。
因此,我深入研究并更改了代码,“get”现在看起来是这样的:

get  
{  
    //double hd = heading_degrees;  
    double hd = 180.0;  
    //double pi = Math.PI;  
    double pi180 = 0.01745329251; //pi / 180;  
    double result = hd * pi180;  
    //double result = 3.14159265359;  
    return result;  
    //return heading_degrees * Math.PI / 180;  
}  
正如你可以从注释出来的行中看到的那样,我尝试了不同的方法,试图找到问题的症结所在。
设置双结果=3.14159265359;是否始终返回3.14159265359,
但是返回双结果=hd*pi180;如上所述,代码不会返回一致的结果。正如你所看到的,航向度现在正好是180.0,只是为了测试和证明输入是完全相同的。 当我第一次点击此代码时,我得到以下结果:
结果=3.1415926518
第二次通过,我得到了这个:
结果=3.1415927410125732

我已经在两台计算机上尝试过这个方法,试图看看这个问题是否是环境问题,但我还无法在不同的IDE上测试它(目前使用的是VS express 2012) 有人知道为什么会这样吗? 我没有在任何地方执行线程(即使执行了,在当前代码迭代中,输入设置为180.0时,它会如何更改结果?) 我似乎发现了一个小线索,那就是对代码做一些小的更改(即使用Math.PI而不是3.3.14159…等等)会在第一时间改变结果。然而,第二次通过的结果似乎总是3.1415927410125732

为这篇冗长的文章道歉

其他说明: 第二次运行只是程序中调用此函数的另一个位置。调试和发布之间没有区别。 使用.NET4

更多测试:

如果获取代码为:

get{ 
double result = 180.0d * 0.01745329251d;
return result;
}
结果是一致的。更准确地说

如果获取代码为:

get{
double hd = 180.0d;
double result = hd * 0.01745329251d;
return result;
}
结果不一致

如果我这样做:

get{
double hd = 180.0d;
double result = (float)(hd * 0.01745329251d);
return result;
}  
结果是一致的,但精确度较低

注意,在上面的测试中,变量都是getter的局部变量
还要注意的是,我只是在运行完整代码时才发现不一致,是不是因为我如何存储getter所属的对象导致了这种情况?
我想我需要再读一遍埃里克·利珀特对其中一个答案的回答。Eric如果你把这两个回复作为答案,我可能会把它们标记为答案。特别是因为上面的最后一个例子和你说的演员差不多

这看起来像金子:

似乎回答了如何走出我自己挖的洞。

特别是当我发现有很多,很多,类似于上面的功能让我头痛

我不知道为什么我的思维会直接跳到release vs debug,但是即使在同一个处理器上,硬件本身也是不一致的。简短的回答是,中间人可以使用更高的精度值,有时会根据被截断的时间生成不同的结果

旧答案:
发行版与调试版之间存在差异。请查看此以了解入门信息


如果需要高度一致的结果,可能需要小数而不是双倍。

能否显示调用和显示结果的代码?最好指向整个项目。最好指向整个项目。现在有点乱,但是。项目:上述代码位于的第250行:从的第313行调用:(两次,第二次运行都是代码的“重播”迭代)您是否对这些值不同的原因感兴趣?或者如何修复他们引入的bug?两者都有。我可能会截断结果并保持足够的准确性来修复它引入的bug,但是为什么很重要,因为它可以帮助我找到可能发生这种情况的其他地方。感谢您的回复,但是这在发布和调试之间没有区别,我编辑了OP来说明这一点。关于小数的问题也不能解释这种不一致性。你编辑的回复中有一个非常有用的链接。我会仔细阅读关于这个问题的回复,因为这个问题最终会导致这个问题。不过,我还没有在该链接中看到任何关于同一处理器上不一致的内容。另外,我使用double的一个原因是因为大多数系统。数学函数需要一个double作为输入,即Math.Cos等。我可能需要重新思考这个问题,并编写自己的数学类…@se5a:这是一个常见问题。例如,参见@se5a:官方行是:编译器可以随心所欲地这样做。实际上,当(1)存在显式强制转换,(2)将值存储到堆位置(即,类类型的字段,或结构位于堆上的结构的字段,或数组元素)时,编译器将截断回“自然”精度除了这些情况,不管出于什么原因,它都可以自由地进行更高精度的数学运算。@se5a:你可能想知道为什么会有这种奇怪的现象。原因是芯片上有少量可用的浮点寄存器,在这些寄存器中进行数学运算(1)更快,(2)更高的精度。但由于它们的数量有限,有时必须将值从寄存器中“踢出”,从而截断它们。寄存器调度的具体细节由实现定义。