【发布时间】:2018-02-14 10:29:32
【问题描述】:
在我正在开发的一些软件的深处有一行代码......
double DataNoise = StatsStuff.MeanofSquares() - average * average;
示例数字:
StatsStuff.MeanofSquares() = 1.9739125181231402E-13
average = -4.3328988592605794E-07
DataNoise = 9.6511265664977283E-15 //(State1)
DataNoise = 9.6511265664977204E-15 //(State2)
如果我反复从 GUI 重新启动分析,该计算的结果迟早会发生变化,有时在第一次重新运行分析时,但它通常会在切换到不同的答案之前给出一些一致的结果(开关前的次数是显着变化的)。一旦软件切换到返回第二个值,它就永远不会返回到返回第一个值。
我正在使用 C# 和 Visual Studio,在带有 i5 4570 的 Windows 7 机器上进行测试,如果这对任何人都有帮助的话。
我在 Debug 和 Release 版本中都发现了这个问题。
每次启动分析时,都会在分析方法中重新创建所有分析对象,因此不应有任何持久性。
我已经记录了计算中的值,它们没有改变;我也使用BitConverter.GetBytes() 来检查数字是否相同。
我已经在网上看到过下面的问题和许多其他类似的文章,但它们都与两台不同机器之间的差异有关。
Why does this floating point calculation give different results...
how-deterministic-is-floating-point-inaccuracy 中的答案似乎表明我应该能够从单个机器和指令集中获得确定性行为,但我没有。
任何帮助解释为什么会发生这种情况和/或如何确保一致的结果将不胜感激。
调试中的一些额外字节值:
输入:
平均:48、51、51、18、221、19、157、190
MeanOfSquares: 205, 250, 200, 243, 196, 199, 75, 61
输出:
数据噪声(状态 1):192、220、244、228、126、187、5、61
DataNoise(状态 2):187、220、244、228、126、187、5、61
【问题讨论】:
-
在使用 IEEE-754 算术时,数字中的低有效位会有微小的差异 - 但结果应该在相同硬件上给定相同输入的情况下是确定性的、环境等。您绝对确定
StatsStuff.MeanOfSquares()正在返回相同 值(System.Double值的所有 64 位)? -
不幸的是它在软件的深处。到目前为止,我还无法在主软件之外复制效果。
-
@Dai:你的说法是绝对错误的。 C# 语言不保证即使在同一进程中,相同的计算也会连续两次给出相同的结果。浮点计算在 C# 中不是确定性的,因为 抖动可以自行决定是否使用高精度寄存器。因此,可以根据寄存器大小以至少 64 位精度或更高的精度进行计算。这会改变计算结果。
-
@Dai:不幸的是,浮点运算在 C# 中不是确定性的,但是如果您想抱怨这种不幸的情况,请向 Intel 抱怨。他们为我们提供了确定性计算速度较慢且准确性较低的芯片组,从而激励语言开发人员将非确定性纳入浮点计算。
标签: c# floating-point