提问人:kuskmen 提问时间:12/19/2017 最后编辑:Pac0kuskmen 更新时间:12/19/2017 访问量:214
为什么在 .NET 中将两个双精度相乘时会发生这种情况 [duplicate]
Why this happens when multiplying two doubles in .NET [duplicate]
问:
在乘以双倍时,我遇到了相当奇怪的行为。
创建一个简单的控制台应用程序,并尝试以下代码。
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
}
我怀疑这是二进制的双重表示,但我无法解释自己这是怎么回事,你能帮我吗?
另外,如果你投射到它以某种方式变成 410......a1
decimal
我尝试针对 C# 3.0 和 C#7.0 进行编译,结果相同。我在Visual Studio 2017中重现了这一点。
答:
编辑
(回答“为什么310==3.1*100”部分)
这只是“偶然”的.3.1 * 100 == 310
只是碰巧浮点运算工作的特定方式,
3.1 * 100 的结果给出 。这个数字与将 310 转换为双精度时得到的结果完全匹配。310.0000...
在这种特殊情况下,比较会很高兴地起作用。
您可以使用 Jon Skeet 的 DoubleConverter.ToExactString() 函数查看它
Console.WriteLine(DoubleConverter.ToExactString(3.1 * 100));
Console.WriteLine(DoubleConverter.ToExactString(4.1 * 100));
// output :
// 310
// 409.99999999999994315658113919198513031005859375
(上一页)
在这种特殊情况下,表达式是 a 乘以 .4.1 * 100D
double
double
同样的错误是由 ( times -> 隐式转换为4.1 * 100
double
int
int
double
)
由于没有为变量指定类型,因此编译器选择将结果解释为 .在这种特殊情况下,由于浮点运算会出现舍入误差(4.1 没有精确的表示形式double
double
)
如果将变量定义为 ,则结果为 ,并且不会发生舍入错误。请注意,您不能只在提供的代码中更改 to,您还必须更改变量: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.
评论
3.1 * 100 == 310
下一个:可靠地将浮点数转换为整数
评论