当然,我们不能将计算结果得到的浮点数进行直接比较判断是否相等,而应该使用一个小的容差值,例如:
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);
然而,我也对更数学的解释感兴趣。任何能够完成以下任务的数学Stackoverflower都可以获得额外的赞:
找到一个反例,其中舍入结果的有效数字少于16位。
确定一组值范围,在这个范围内,舍入结果将始终“一致”,如此处定义的(例如,所有舍入结果中有效数字的数量< N的所有值)。
提供一种算法方法来生成反例。