这个C#财务计算中的浮点问题在哪里?

时间:2011-04-26 08:48:13

标签: c# algorithm floating-accuracy

我收到交易分配的FIX消息,其中价格以美分(ZAR / 100)给出,但佣金在 Rands 中给出。这些值由常量表示。运行此计算时,commPerc1显示的值为0.099999999999999978,commPerc2显示为0.1。这些值看起来相差x10,但通过检查计算回 Rands commRands1commRands2分别显示非常相似的值336.4831554和336.48315540000004。

private const double Price = 5708.91;
private const double Qty = 5894;
private const double AbsComm = 336.4831554;

static void Main()
{

    double commCents = AbsComm * 100;
    double commPerc1 = commCents / (Qty * Price) * 100;
    double commRands1 = (Qty * Price) * (commPerc1 / 100) / 100;

    double commPerc2 = (AbsComm / (Qty * (Price / 100))) * 100;
    double commRands2 = (Qty * Price) * (commPerc2 / 100) / 100;
}

请注意: 我在这里处理遗留代码,其中转换为十进制将涉及多个更改和QA,所以现在我必须接受double

7 个答案:

答案 0 :(得分:5)

浮点问题无处不在,因为所有的值都是double类型,这是一种双精度浮点类型,而不是基数为10的数字类型。 (因此,正在执行的所有计算都是浮点计算。)

您应该声明变量decimal。这种类型的目的恰恰是为了进行财务计算。

答案 1 :(得分:5)

使用double进行财务计算,请改用decimal。浮点数对于物理测量值是可以的,其中值无论如何都不是精确的。但是对于财务计算,您使用精确值,由于浮点表示,您无法承担错误。这就是decimal的用途:

  

十进制值类型适用于需要大量有效积分和小数位且没有舍入误差的财务计算。

(from MSDN)

答案 2 :(得分:4)

  

运行此计算时,commPerc1显示的值为0.099999999999999978commPerc2显示0.1。这些值看起来相差x10

不,他们没有。只存在无限小(但现有)的舍入差异。正如其他人已经指出的那样,你永远不应该使用需要绝对精度的计算的浮点数。对于浮点,你总是有像这样的舍入错误,例如金融客户不喜欢在书中丢失或额外便士/美分。

答案 3 :(得分:2)

这是由于浮点数存储在内存中的方式。在处理财务计算时,您可以使用decimal代替doublefloat

答案 4 :(得分:1)

应使用Decimal数据类型执行财务计算。双精度存储指定数字的“近似值”,因为指定的数字无法完美地存储在指定的位分配中。

答案 5 :(得分:1)

0.0999999999999999780.1相差10倍,它们几乎相同。就像0.999几乎是1。

但您确实应该使用Decimal代替Double来进行财务计算。 Double无法准确表示0.1等数字,Decimal可以。 (另一方面,两者都不能完全代表1/3)。

此外Decimal有一个更大的尾数,并在发生溢出时抛出异常。

答案 6 :(得分:1)

请使用小数进行货币计算。

看看Here