0

I receive a FIX message for a trade Allocation, where Price is given in cents (ZAR / 100), but commission is given in Rands. These values are represented by the constants. When I run this calculation, commPerc1 shows a value of 0.099999999999999978, and commPerc2 shows 0.1. These values look to differ by x10, yet with the check of calculating back to Rands, both commRands1 and commRands2 show very similar values of 336.4831554 and 336.48315540000004 respectively.

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;
}

PLEASE NOTE: I am dealing with legacy code here where a conversion to decimal would involve several changes and QA, so right now I have to accept double.

ProfK
  • 49,207
  • 121
  • 399
  • 775
  • 6
    Why the hell do you use `double` instead of `Decimal` for financial calculations? – CodesInChaos Apr 26 '11 at 08:49
  • Where do you see a 10x difference? `0.099... = 0.1`, what you're seeing is the effect of some floating point error, nothing special. `commPerc1` is equal to `commPerc2`, ignoring those insignificant errors. – AVH Apr 26 '11 at 08:56

7 Answers7

5

The floating point problem is everywhere, because all of your values are of type double, which is a double-precision floating-point type, not a base-10 numeric type. (Hence, all calculations being performed are floating-point calculations.)

You should declare your variables decimal instead. That type is purposed precisely for financial calculations.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
5

Don't use double for financial calculations, use decimal instead. Floating point numbers are OK for physical, measured values, where the value is never exact anyway. But for financial calculations you're working with exact values, you can't afford errors due to floating point representations. That's what decimal is made for:

The Decimal value type is appropriate for financial calculations requiring large numbers of significant integral and fractional digits and no round-off errors.

(from MSDN)

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
4

When I run this calculation, commPerc1 shows a value of 0.099999999999999978, and commPerc2 shows 0.1. These values look to differ by x10

No they don't. There is only an infinitely small (but existing) rounding difference between. As others have already noted, you should never use floating point with calculations that demand absolute precision. With floating point you always have rounding errors like this, and e.g. financial clients don't like missing or extra pennies/cents in their books.

Péter Török
  • 114,404
  • 31
  • 268
  • 329
2

That's due to the way floating numbers are stored in memory. You could use decimal instead of double or float when dealing with financial calculations.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
1

Financial calculations should be carried out using the Decimal datatype. Doubles store 'approximations' of the specified number since the specified number can't be stored perfectly within the specified bit-allocation.

cusimar9
  • 5,185
  • 4
  • 24
  • 30
1

0.099999999999999978 and 0.1 don't differ by a factor of 10, they are almost the same. Just like 0.999 is almost 1.

But you really should use Decimal instead of Double for financial calculations. Double can't exactly represent numbers like 0.1 whereas Decimal can. (On the other hand neither can represent 1/3 exactly).

Additionally Decimal has a larger mantissa and throws exceptions when overflows occur.

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
1

Please use decimal for monetary calculations.

Have a look Here

Community
  • 1
  • 1
V4Vendetta
  • 37,194
  • 9
  • 78
  • 82