为什么在.net中乘以两倍时会发生这种情况



我在倍增时面对相当奇怪的行为。

制作一个简单的控制台应用程序并尝试以下代码。

private static void Main(string[] args)
{
    var b1 = 3.1 * 100D;
    var a1 = 4.1 * 100D;
    // put breakpoint here and observe b1 and a1 values, to me they are  
    // b1=310, a1=409.99999999999994
    Console.WriteLine(a1);
    // notice that Console.WriteLine actually returns 410
}

我怀疑这是二进制中的双重表示,但我无法解释自己是怎么可能的,您能帮我吗?

另外,如果您将a1铸造为decimal,它将以某种方式变为410 ...

我尝试针对C#3.0和C#7.0编译,都给出了相同的结果。我正在Visual Studio 2017中复制此内容。

编辑

(要回答"为什么310 == 3.1 * 100"部分)

这只是"偶然的" 3.1 * 100 == 310

碰巧的是,浮点算术的特定方式工作,3.1 * 100的结果给出了310.0000...。如果将310转换为双重,则此数字与您获得的结果完全匹配。

在这种特殊情况下,比较将愉快地工作。

您可以使用doubleconverter.toexactstring()函数来查看jon skeet

    Console.WriteLine(DoubleConverter.ToExactString(3.1 * 100));
    Console.WriteLine(DoubleConverter.ToExactString(4.1 * 100));
    // output : 
    // 310
    // 409.99999999999994315658113919198513031005859375

(上一个)

在这种特殊情况下,表达式4.1 * 100Ddouble乘以double

4.1 * 100doubleint-> int被隐式施放为double

由于未为您的变量指定任何类型,因此编译器选择将结果解释为double。在这种特殊情况下,由于浮点算术造成的四舍五入误差(4.1没有确切的表示为double

如果将变量定义为decimal,则结果是decimal,并且不会发生舍入误差。请注意,您不能仅将var更改为您提供的代码中的decimal,也必须更改变量:

在这种情况下,乘法将在两种情况下都给出确切的值。

更多地在浮点数错误上:浮点数学是否损坏?

decimal a1 = 4.1 * 100D; // compilation error : no implicit cast from double to decimal
decimal a1 = 4.1M * 100; // valid, and the multiplication will be performed exactly.

相关内容

  • 没有找到相关文章

最新更新