不,这不是另一个"为什么是(1/3.0)*3!= 1"的问题.
我最近一直在读关于漂浮点的事情; 具体而言,相同的计算如何在不同的体系结构或优化设置上给出不同的结果.
对于存储重放的视频游戏来说,这是一个问题,或者是对等网络(而不是服务器 - 客户端),它依赖于每次运行程序时产生完全相同结果的所有客户端 - 一个小的差异浮点计算可能导致不同机器(甚至是同一台机器上)的游戏状态截然不同!
甚至在"跟随" IEEE-754的处理器中也会发生这种情况,这主要是因为某些处理器(即x86)使用双倍扩展精度.也就是说,它们使用80位寄存器进行所有计算,然后截断为64位或32位,导致与使用64位或32位进行计算的机器不同的舍入结果.
我在网上看到过这个问题的几种解决方案,但都是针对C++,而不是C#:
double使用_controlfp_s(Windows),_FPU_SETCW(Linux?)或fpsetprec(BSD)禁用双扩展精度模式(以便所有计算使用IEEE-754 64位).float和double完全.decimal可以用于此目的,但会慢得多,并且没有任何System.Math库函数支持它.那么,这在C#中是否也是一个问题? 如果我只打算支持Windows(而不是Mono)怎么办?
如果是,有没有办法强制我的程序以正常的双精度运行?
如果没有,是否有任何库可以帮助保持浮点计算的一致性?
我有一个用C#编写的程序,有些部分是用本机C/C++编写的.我使用双精度来计算某些值,有时由于精度太低而导致结果错误.经过一番调查后,我发现有人正在将浮点精度设置为24位.当我将精度重置为至少53位(使用_fpreset或_controlfp)时,我的代码工作正常,但我仍然需要确定谁负责将精度设置为24位.
我能做到这一点的任何想法?
考虑以下简单程序:
var dblMax = Double.MaxValue;
var result = (dblMax * 1000) / 1800;
Console.WriteLine(result);
Run Code Online (Sandbox Code Playgroud)
当我在调试模式下构建它并运行 (Ctrl+F5) 或调试 (F5) 时,它会打印9.987140856842E+307.
当我切换到 Release 模式并运行 (Ctrl+F5) 它时,它会8无限打印。
我知道这种差异是由于在发布模式下完成的一些编译器优化造成的。
但是,如果我在发布模式下调试 (F5)相同的构建,它会9.987140856842E+307再次打印 !
我正在调试的事实如何改变计算结果?
编辑:
我不问为什么调试模式和发布模式会产生不同的结果。我想知道为什么发布模式会根据我是否调试 (F5) 或不调试 (Ctrl+F5) 产生不同的结果。