相关疑难解决方法(0)

浮点数学是否破碎?

请考虑以下代码:

0.1 + 0.2 == 0.3  ->  false
Run Code Online (Sandbox Code Playgroud)
0.1 + 0.2         ->  0.30000000000000004
Run Code Online (Sandbox Code Playgroud)

为什么会出现这些不准确之处?

language-agnostic math floating-point floating-accuracy

2798
推荐指数
28
解决办法
28万
查看次数

为什么.NET使用银行家的舍入作为默认值?

根据文档,该decimal.Round方法使用round-to-even算法,这对于大多数应用程序来说并不常见.所以我总是最终编写一个自定义函数来做更自然的圆半算法:

public static decimal RoundHalfUp(this decimal d, int decimals)
{
    if (decimals < 0)
    {
        throw new ArgumentException("The decimals must be non-negative", 
            "decimals");
    }

    decimal multiplier = (decimal)Math.Pow(10, decimals);
    decimal number = d * multiplier;

    if (decimal.Truncate(number) < number)
    {
        number += 0.5m;
    }
    return decimal.Round(number) / multiplier;
}
Run Code Online (Sandbox Code Playgroud)

有谁知道这个框架设计决策背后的原因?

是否有任何内置的圆形半算法实现到框架中?或者可能是一些非托管Windows API?

对于初学者而言,这可能会产生误导,因为他们只是写了一个decimal.Round(2.5m, 0)期望3但结果是2.

.net rounding

264
推荐指数
4
解决办法
5万
查看次数

Windows .NET更新后,最后一位数字的舍入取整

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 …

c# floating-point .net-4.8

11
推荐指数
1
解决办法
256
查看次数