由于浮点数的二进制存储,避免意外行为的最佳方法是什么?

Cra*_*g W 4 .net c# binary

我最近写了一个简单的for循环,并得到了一些意想不到的行为:

for(double x = 0.0; x <= 1.0; x += 0.05)
{
    Console.WriteLine(x.ToString());
}
Run Code Online (Sandbox Code Playgroud)

这是输出:

0
0.05
0.1
0.15
0.2
0.25
0.3
0.35
0.4
0.45
0.5
0.55
0.6
0.65
0.7
0.75
0.8
0.85
0.9
0.95
Run Code Online (Sandbox Code Playgroud)

请注意,即使继续for循环的条件似乎包含它,也不会出现1.我意识到这是因为十进制数字作为二进制存储在内存中, 1实际上不是1,而是实际上是1.0000000000000002(根据Visual Studio中的变量监视).所以我的问题是,避免这种意外行为的最佳方法是什么?一种方法是使用decimal类型而不是double,但大多数System.Math函数double仅在s上工作,并且两者之间的转换并不简单.

Mar*_*ers 9

不要测试双打的平等性.

在这里你可以使用整数运算:

for (int i = 0; i <= 20; ++i)
{
    double x = (double)i / 20.0;
    Console.WriteLine(x);
}
Run Code Online (Sandbox Code Playgroud)

在其他情况下,测试两个双精度数之间的差异是否足够小而不是使用相等比较可能更合适.