我在我的代码中偶然发现了一个方法,其中在我的代码中计算了舍入值。 我知道比较双值产生意外结果的问题。
实施例
double x = 19.08;
double y = 2.01;
double result = 21.09;
if (x + y == result)
{
// this is never reached
}
此处的说明:http://csharpindepth.com/Articles/General/FloatingPoint.aspx
但是,到目前为止,我预计Math.Round()方法即使是双值也是准确的。
看看这段代码。
var decimals = 2;
var value1 = 4.725;
var value2 = 4.725M;
var result1 = Math.Round(value1, decimals, MidpointRounding.ToEven);
var result2 = Math.Round(value1, decimals, MidpointRounding.AwayFromZero);
var result3 = Math.Round(value2, decimals, MidpointRounding.ToEven);
var result4 = Math.Round(value2, decimals, MidpointRounding.AwayFromZero);
Console.WriteLine("Double (ToEven): {0}", result1); // outputs 4.72
Console.WriteLine("Double (AwayFromZero): {0}", result2); // outputs 4.72 (expected: 4.73)
Console.WriteLine("Decimal (ToEven): {0}", result3); // outputs 4.72
Console.WriteLine("Decimal (AwayFromZero): {0}", result4); // outputs 4.73
对我来说,结果2应该是4.73是完全清楚的。但事实并非如此。 有人可以解释原因吗?
答案 0 :(得分:10)
好吧,您可能想重新考虑一下“完全清楚”的概念,因为4.725(而不是4.625)不能用double
完全表示。它实际上正是
4.7249999999999996447286321199499070644378662109375
请记住,浮点数只是实数数学概念的近似值 - 许多关于数字应如何表现的直观概念都不适用。最终得到的值大约 4.725,但显然略低于它。因此,中点舍入模式在此处不执行任何操作,因为它不是两个可能的数字之间的中间点。
答案 1 :(得分:1)
您的value1
可能很容易4.724999999999999999999999999999999
。为什么要将其四舍五入到4.73
而不是4.72
?
答案 2 :(得分:0)
使用Double值检查相等性时始终存在问题。添加两个双倍值,如0.5 + 0.5,将不会是1.0,但最有可能达到0.99999和1.00001。这与使用浮点数的二进制到十进制的转换有关。
您应该在舍入错误/精度部分检查以下内容: http://www.learncpp.com/cpp-tutorial/25-floating-point-numbers/ 它提供了一些关于浮点精度的有价值的见解,C#也应遵循这个案例。
答案 3 :(得分:0)
使用Convert.ToDouble(value1.ToString(" f2"))而不是Math.Round(value1,2)