如何处理十进制运算错误?

时间:2017-06-19 09:54:30

标签: c# decimal

我有一个值的缩放函数,看起来像这样:

r = a/b*c;

其中r,a,b,c是小数。

大多数时候,它都能正常工作,但有时候会得到这样的结果:

1.5M/3.09785668M*3.09785668M => 1.5000000000000000000000000001M

这对我来说是一个问题,因为在我的计算中,随着时间的推移,错误会升级。

检测和删除此类错误的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

<强>检测

r = a/b*c;
Debug.Assert(r*b/c == a, "Not good");

避免非终止子结果,但仍然容易受到精确丢失和非终止最终结果的影响

r = a*c/b;

基本上,两种有问题的子结果是(1)有限精度损失和(2)非终止数

(1):

var loss1 = 1.000000000000000000001m * 1.000000000000000000001m;
// should be 1.000000000000000000002000000000000000000001m
// will be be 1.000000000000000000002m

(2):

var loss2 = 1m/3m;
// should be 0.333333333333333333333.. infinite line of 3
// will be be 0.3333333333333333333333333333M

第一种可以发生在乘法和除法上,第二种只能在除法上发生。第一种可以通过增加精度来修复,第二种只能通过按原样携带分数来修复,而不是试图创建任何有限精度的单个实数。