0

There is an input to my software for processing: float totalPurchased. I am coding with C++11/GCC/GDB/Linux.

The totalPurchase price informed is 14.92 as it is read from a file.

However, when the program runs, it shows 14.920001 out of no where. I don't want to round the value 14.92 to up 15.00 or down 14.00; the only thing I really need is to have the input right, without the compiler adding up things that does not exist as input.

The problem is that this 0.000001 is breaking a part the whole software calculation in the long run.

How to get rid of this 0.000001, and make sure that it appears the actual value that was read from the file into my float variable: 14.92?

All comments and suggestions are highly appreciated.

Community
  • 1
  • 1
  • 1
    Please provide a [mcve]. – Sam Varshavchik Feb 25 '16 at 23:40
  • 2
    This is why you generally should not use floating point types for money amounts. Use an integer representing the number of cents. – aschepler Feb 25 '16 at 23:40
  • @aschepler - thank you! I will check this approach. – Daniela Martínez Feb 25 '16 at 23:42
  • 1
    Note that in some jurisdictions, and for some use cases (e.g. gasoline prices), currency units *smaller* than one cent are used, so it might be better to represent money as integer multiples of 1/10 of a cent. Related: [Wikipedia article on the use of "mill"as a currency unit](https://en.wikipedia.org/wiki/Mill_%28currency%29) – njuffa Feb 25 '16 at 23:50

2 Answers2

4

Unfortunately, floating point can't represent your number exactly: 14.92 is a repeating fraction in binary.

The question you want to ask yourself is: why does such a small offset break your calculation? If you really need to compare values so exactly, then perhaps floating point is not the appropriate datatype.

If you need something like, say, an exact percentage, or an exact number of cents, you can store 100* the number. This is a persistent problem in accounting, which is why accountants don't use floating point to add their money.

comingstorm
  • 25,557
  • 3
  • 43
  • 67
1

Use a fixed point library such as this.

For myself, in this domain, I would store price as integer pennies and do something along the line of

sprintf("%i.%02i", price/100, price%100)

Caveats for negative numbers, and in some applications you might want sub-penny precision, but you get the idea. A full fixed-point library is overkill for things like this, I think.

Actually, because I like to Do The Right Thing I would do something like this

class CashValue
{
public:
    static CashValue parse (const std::string &);
    float to_float () const;
    CashValue & operator + (const CashValue &);
    // etc
private:
    int m_pennies;
};

Thus making the significance of the unit explicit. Only support operations for which exact solutions exist. If you want to do something like this

price *= pow (1.0 + (percent_interest/100.0), years)

then my interface would force you to verbosely convert it first, making you think about the issues when they become relevant, but still supporting safe operations such as addition transparently and accurately.

spraff
  • 32,570
  • 22
  • 121
  • 229