Jar*_*v K 11 c# floating-point .net-4.8
Windows更新之后,某些计算值的最后一位已更改,例如,从-0.0776529085243926更改为-0.0776529085243925925。更改总是下降一个,并且偶数和奇数都会受到影响。这似乎与KB4486153有关,因为还原此更新会将值更改回以前的值。
在Visual Studio中进行调试并将鼠标悬停在变量上时,已经可以看到此更改。稍后将该值写入输出文件,并在其中进行更改(不运行调试器)。
最小的可复制示例
var output = -0.07765290852439255;
Trace.WriteLine(output); // This printout changes with the update.
var dictionary = new Dictionary<int, double>();
dictionary[0] = output; // Hover over dictionary to see the change in debug mode
Run Code Online (Sandbox Code Playgroud)
背景
计算值来自
output[date] = input[date] / input[previousDate] - 1;
Run Code Online (Sandbox Code Playgroud)
不管浮点运算的精度损失如何,我都可以在“即时”窗口中进行计算,并获得-0.07765290852439255升级前后的信息。
但是,将鼠标悬停在output变量上时,我看到
{[2011-01-12 00:00:00, -0.0776529085243926]}了升级之前和
{[2011-01-12 00:00:00, -0.0776529085243925]}之后的情况,并且这种差异也传播到了输出文件中。
看起来更新前后的计算值是相同的,但是其表示方式四舍五入。
输入值为
{[2011-01-11 00:00:00, 0.983561000400506]}
{[2011-01-12 00:00:00, 0.907184628008246]}
Run Code Online (Sandbox Code Playgroud)
目标框架设置为 .NET Framework 4.6.1
题
在保持更新的同时,我可以做些什么来得到以前的行为?
我知道浮点计算的精度损失,但是为什么在更新后会发生这种变化,又如何保证未来的更新不会改变值的表示呢?
KB4486153是Microsoft .NET Framework 4.8的更新,请参阅https://support.microsoft.com/en-us/help/4486153/microsoft-net-framework-4-8-on-windows-10-version-1709- Windows 10版本
OP 遇到了浮点数学的常见问题之一。对于新软件,人们想要一致的答案还是最佳的答案?(升级后效果更好)
一些有助于推进问题的信息。
var output = -0.07765290852439255;
Run Code Online (Sandbox Code Playgroud)
对于常见的binary64编码1,由于 binary64 的二进制性质,output其精确值为
-0.077652908524392 54987160666132695041596889495849609375
Run Code Online (Sandbox Code Playgroud)
下面显示了前一个和后一个可能的double十六进制和十进制 FP。
-0.077652908524392 5
-0x1.3e10f9e8d3217p-4 -0.077652908524392 53599381885351249366067349910736083984375
-0x1.3e10f9e8d3218p-4 -0.077652908524392 54987160666132695041596889495849609375
-0.077652908524392 55
-0x1.3e10f9e8d3219p-4 -0.077652908524392 56374939446914140717126429080963134765625
-0.077652908524392 6
Run Code Online (Sandbox Code Playgroud)
少一位数字的最佳四舍五入到最接近值-0.077652908524392 55(其编码完全为-0.077652908524392 5498...)为-0.077652908524392 5。升级后,代码会打印更好的答案 - 至少在这种情况下是这样。
我不认为这是一个四舍五入的变化,而是对文本转换的改进。
我可以做些什么来在保持更新的同时获得以前的行为吗?
也许吧,但看起来更新带来了更好的结果。
我们如何保证未来的更新不会改变值的表示
使用十六进制浮点输出(与"%a"C 中一样)是一种在不改变表示形式的情况下获得增益的方法,但非十进制输出并不常见。
1对于其他编码,确切的值可能比-0.077652908524392 6更接近-0.077652908524392 5。