如何处理无限重复的数字作为小数?

GBl*_*ney 10 c# rounding-error rounding

当除法产生无限重复的数字时,数字显然会被截断以适合小数的大小.所以像1/3这样的东西就像0.3333333333333333333.如果我们然后将该数字乘以3,我们得到类似于0.999999999999999999而不是1,如果保留了该分数的真实值,我们将获得.

这是来自MSDN上十进制文章的代码示例:

decimal dividend = Decimal.One;
decimal divisor = 3;
// The following displays 0.9999999999999999999999999999 to the console
Console.WriteLine(dividend/divisor * divisor); 
Run Code Online (Sandbox Code Playgroud)

当值0.9999999999999999999与1进行比较时,这会导致问题.如果不失去精确度,它们就会相等,但当然在这种情况下,比较会导致错误.

人们通常如何处理这个问题?除了为每次比较定义一些误差之外,还有更优雅的解决方案吗?

Sin*_*ian 5

这是一个非常古老且广为人知的数值计算问题.您已经说过,除了为每次比较定义一些误差之外,您正在寻找解决方案.我想到的一种方法是首先在内存中构建数学表达式树,然后进行计算.掌握了这一点,我们可以在进行计算之前使用一些已知规则进行一些简化.规则如:

  • 如果它们不为零,则删除分数的分子和分母中的相等数字
  • 数字的平方根是数字本身
  • ...

.因此代替它等于0.33333十进制/双精度值存储1/3 ...我们可以存储的实例Fraction(1, 3).然后我们可以定义这样的所有其他表达式来构建表达式而不是进行计算.最后,我们可以先用上面的规则简化表达式,然后计算结果.

我在网上搜索了一下,找到了这样做的库,但还没找到.但我相信其他语言/平台甚至.NET都可以找到一些.

请注意,上述方法最终会产生更好的结果,但却无法解决数值计算本质所固有的问题.