当然,永远不要比较由相等性计算得出的浮点值,而应始终使用较小的容差,例如:
double value1 = ...
double value2 = ...
if (Math.Abs(value1 - value2) < tolerance * Math.Abs(value1))
{
... values are close enough
}
但是,如果我使用 Math.Round,我是否可以始终确保结果值是一致的,即即使舍入后的值是不能由 double 值精确表示的值,以下 Assert 是否总是成功?
public static void TestRound(double value1, double value2, int decimals)
{
double roundedValue1 = Math.Round(value1, decimals);
double roundedValue2 = Math.Round(value2, decimals);
string format = "N" + decimals.ToString();
if (roundedValue1.ToString(format) == roundedValue2.ToString(format))
{
// They rounded to the same value, was the rounding exact?
Debug.Assert(roundedValue1 == roundedValue2);
}
}
如果不是,请提供一个反例。
编辑
感谢 astander对于由蛮力产生的反例,证明结果在一般情况下不“一致”。这个反例在四舍五入的结果中有 16 位有效数字——它在缩放时也以同样的方式失败:
double value1 = 10546080000034341D;
double value2 = 10546080000034257D;
int decimals = 0;
TestRound(value1, value2, decimals);
但是,我也对更数学化的解释感兴趣。任何更数学化的 Stackoverflowers 都可以做以下任何一项:
最佳答案
好吧,这似乎是一个非常技术性的问题,所以我认为蛮力可能会告诉我们。
我尝试了以下
public static void TestRound(double value1, double value2, int decimals)
{
double roundedValue1 = Math.Round(value1, decimals);
double roundedValue2 = Math.Round(value2, decimals);
string format = "N" + decimals.ToString();
if (roundedValue1.ToString(format) == roundedValue2.ToString(format))
{
// They rounded to the same value, was the rounding exact?
if (roundedValue1 != roundedValue2)
{
string s = "";
}
}
}
private void button1_Click(object sender, EventArgs e)
{
for (double d = 0, inc = .000001; d < 1000; d += inc)
for (int p = 0; p <= 15; p++)
TestRound(Math.Pow(Math.Pow(d, inc), 1 / inc), d, p);
}
我在 "string s = "";"上放置了一个断点当它进入这个部分时检查,
并输入以下值
value1 = 1.0546080000034341
value2 = 1.0546080000034257
decimals = 15
roundedValue1 = 1.0546080000034339
roundedValue2 = 1.0546080000034259
roundedValue1.ToString(format) = 1.054608000003430
roundedValue2.ToString(format) = 1.054608000003430
我想这就是你要找的答案?
如果没有,请告诉我,以便我可以测试更多。
关于.net - Math.Round(double,decimal) 是否总是返回一致的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1832335/