0

I have a stock selling/buying program, where the user can say how much of a stock they wish to buy and sell. Everything works fine, until the user wants to sell a stock for $4.10 for $5.10. In order to do math easier with the floating point, I convert the double to an int: 10.10 becomes 1010, and so on. Whenever I cast 4.10 to an int, it becomes 409, and the same occurs for 5.10.

The money is stored in a class, Dollars. Inside of this class, when I call a constructor, I can either call Dollars(int cents): cents(cents) {} or Dollars(double dollars): cents(0) { *this = dollars; }. When the double constructor is used, it uses the following cents = (int)(dollars * 100.0); to cast the given double into an int.

I've tried using the (int)(double) cast method inside the class to convert into an int, and I've also tried casting into an int before, and using the int constructor, but neither have worked.

I expect the output of this cast to be 410 when I feed it 4.10, but it always comes out to 4.09.

Nathan Lundgren
  • 79
  • 3
  • 14
  • 1
    See [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – 1201ProgramAlarm May 11 '19 at 20:43
  • Check out for the [_Money Pattern_](https://www.martinfowler.com/eaaCatalog/money.html). Your customer bookkeepers will be thankful and satisfied. – πάντα ῥεῖ May 11 '19 at 20:45
  • 2
    Don't use floats for currency. Also `4.10*100` is likely `409.999999...` and conversion to int simply truncates. In this case you will get more precise results by first calling `std::round` – Quimby May 11 '19 at 20:45
  • @Quimby, I wonder, why many folks post their right answers as comments (and so you do too)? this way many questions end up unanswered, while the correct answer is in the comments. – Dmitry May 11 '19 at 23:13
  • @Dmitry I expected this answer to get closed as duplicate or something like that. It's only two lines, didn't seem enough for an answer. But you might be right. – Quimby May 12 '19 at 10:42

1 Answers1

1

Don't use floats for currency. Also 4.10*100 is likely 409.999999... and conversion to int simply truncates. In this case you will get more precise results by first calling std::round. It won't solve all rounding errors. There still will be cases where the result won't be correct just because double has 52-bit mantissa and int can/will be 64-bit if compiled for x64 platform.

The last problem can be sometimes solved by long double if there's a support for it. That is sizeof(long double)>sizeof(double) which is not guaranteed.

The easiest correct implementation is to simply use uint64_t and do all calculations in e.g. cents. Then all math operations are precise. In real-life when a bank calculates interest it rounds the result too, there's no need for floating precision. Correct printing is then: cout<<amount/100<<"dollars "<<amount%100<<"cents";

Quimby
  • 17,735
  • 4
  • 35
  • 55