-3

I am doing addition of prices in my application. I have values as QStrings and I convert to float and add. When it reaches high value, result is not precise. I read like float or double should not be used for currency addition and use separate variable for integer part and fractional part. My code and log is below:

qDebug ("m_totalPrice: %f + %f =", m_totalPrice, item.price.toFloat());
m_totalPrice += item.price.toFloat();
qDebug ("m_totalPrice: %f", m_totalPrice);
ui->totalLabel->setText(QString::number(m_totalPrice, 'f', 2));  

m_totalPrice is float and item.price is QString

logs:

  1. m_totalPrice: 424659.500000 + 22350.500000 =
    m_totalPrice: 447010.000000
  2. m_totalPrice: 447010.000000 + 18.900000 =
    m_totalPrice: 447028.906250
  3. m_totalPrice: 447028.906250 + 125.900002 =
    m_totalPrice: 447154.812500
  4. m_totalPrice: 447154.812500 + 125.900002 =
    m_totalPrice: 447280.718750
  5. m_totalPrice: 447280.718750 + 11.500000 =
    m_totalPrice: 447292.218750
  6. m_totalPrice: 447292.218750 + 22.500000 =
    m_totalPrice: 447314.718750

Error is from line 2. Can someone tell how to resolve this?

Edit : since my question is not complete
In line 2 it shows addition of 447010.000000 + 18.900000 = 447028.906250
My doubt is after addition it should be at least 447028.9000..

AAEM
  • 1,837
  • 2
  • 18
  • 26
A.J
  • 725
  • 10
  • 33
  • 2
    If you rely on the "toFloat()" function in QString you should consider to check for the value of "ok" 'toFloat ( bool * ok = 0 )' after the conversion to be sure it worked. – TWE Jun 25 '14 at 11:23
  • ok check value will notify the conversion status success or not. It gives not clue on the accuracy – A.J Jun 25 '14 at 11:41
  • Some values just can't be represented exactly as [float](http://en.wikipedia.org/wiki/Single_precision). This is why if you need numbers to add up exactly (like with currency), you use integers or Decimal types. – Leiaz Jun 25 '14 at 12:27
  • aside from the limited precision of float, [Is floating point math broken?](http://stackoverflow.com/q/588004/995714) – phuclv Feb 06 '17 at 08:16

1 Answers1

2

There are several factors to consider here.

  1. Float has only about 6 digits of precision, and that's rather easy to exceed. You can fix that by using double, which gives you about 15 digits.
  2. Decimal fractions stored as floating point numbers are approximate. When you add them up the errors accumulate, and when you subtract then you lose precision. You can fix that by storing all your currency values as cents (rather than dollars) or even hundredths of a cent and converting/formatting as needed.
  3. If you do that, then whenever you multiply or divide you must round to the nearest integer (cent or whatever) to avoid accumulating errors.

What I'm recommending here as the simple solution is to use doubles as extended precision integers, which will work find up to 15 digits or some trillions of dollars, expressed in cents.

However, if you're really serious about currency calculations, you need to find and use a Fixed Decimal arithmetic package. The investment will be worth it.

And I agree: never use float!

david.pfx
  • 10,520
  • 3
  • 30
  • 63
  • Glad to hear it, but bear the rest of what I wrote in mind. Sooner or later you will run into another problem... – david.pfx Jun 25 '14 at 14:31
  • ok.. meanwhile ill try for so alternate way to handle.. Since I am doing application related to point-of-sale, i have lot of mathematical operations has to be performed.. so it is difficult to handle integer and decimal seperately – A.J Jun 25 '14 at 15:14
  • I agree. So my suggestion is: use scaled double or fixed decimal, but not integers. That's way too hard. – david.pfx Jun 26 '14 at 05:47