5

Is it safe to store prices in double variable in C++? In C# and Java you can use Decimal. (They also say that storing prices in double is very bad idea). What should I do in C++?

Zong
  • 5,701
  • 5
  • 27
  • 46
user3555886
  • 93
  • 1
  • 4
  • What about float? Why is a bad idea?. – ElBaulP Apr 21 '14 at 07:56
  • How many decimal digits do you need for the fractional part? Does it vary or is it fixed? – amdn Apr 21 '14 at 07:56
  • also see http://stackoverflow.com/questions/14096026/c-decimal-data-types – stijn Apr 21 '14 at 07:56
  • 2
    Because unless you are dealing with accounting systems, and having multiple percentage multiplication's. Double is overkill, it certainly is a bad idea last time. But as time move on, double is nothing to most computer systems. – PicoCreator Apr 21 '14 at 08:04
  • Related read is this paper http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2849.pdf – Casper Beyer Apr 21 '14 at 08:14

7 Answers7

5

If the price range is suitable (probably it is), you can use long long with an implied dot before the last two digits. So, 12000 will mean 120.00. It's called "fixed point" arithmetic. But you need to take care of multiplications of two currency values (why would you need it anyway).

cyco130
  • 3,971
  • 16
  • 27
  • No, multiplying two currencies will give wrong results: 100*100=10000. Now you need four digits after the dot. But I understand that it's a rare situation. Most of the time you'll just multiply a currency ad a unitless quantity. – cyco130 Apr 21 '14 at 10:29
2

You can have a look at Intel® Decimal Floating-Point Math Library for storing price. Also you can check the Boost.Multiprecision library which can be very useful, you can use decimal based floating point template class called cpp_dec_float

Rahul Tripathi
  • 152,732
  • 28
  • 233
  • 299
2

Unfortunately, you have the same Problem in C++ as everywhere else. You can't trust double to store the values correctly, although its much better than a float.

There's no data-structure like Decimal avaiable in C++, so you either need to look for a Library that does this for you, you you use an other format.

A simple solution would be, to store the value "42.37" as "4237" - this is how you can trust you values. But I would still recommend using double, if you are calculating with this numbers.

If you decide to use bigger variable-types like long double, you can reduce the possibilty that something goes wrong - but it doesn't guarantee it.

maja
  • 14,242
  • 14
  • 72
  • 106
2

I'd be tempted store prices in terms of the smallest fraction of currency you care about using int or unsigned int. So if an item costs $5.99 and you don't track values smaller than one cent, store it in an int as 599.

user3553031
  • 5,479
  • 1
  • 17
  • 38
2

You can use long double to store the price

// get_money manipulator example
#include <iostream>     // std::cin, std::cout
#include <iomanip>      // std::get_money

int main ()
{
  long double price;
  std::cout << "Please, enter the price: ";
  std::cin >> std::get_money(price);

  if (std::cin.fail()) std::cout << "Error reading price\n";
  else std::cout << "The price entered is: " << price << '\n';

  return 0;
}
humam
  • 181
  • 5
1

Depends on accuracy that you need. If you are going to work with numbers like 5.25, 9.14, etc., you don't even need double. float will be good enough.

If you are going to work with account balance and add 0.01% to number like 18 570.548911545, then precision of 15 decimal digits that double provides will be enough.

If you need a slightly higher precision, go for long double. If that's not enough, only then look for "more precise alternative".

LihO
  • 37,789
  • 9
  • 89
  • 156
  • 1
    The Problem is, that float and double-values can't store all decimal-numbers precicely. If you try to store "0.1 dec", it becomes to "0.0001100110011001100110... bin". If you convert it back, its "0.09999... dec". This can lead to a problem, when you are calculating with such numbers. Using bigger types reduces the possibilty of such problems, but it doesn't guarantee that it's working. – maja Apr 21 '14 at 08:02
  • @maja: Yeah. I'm well aware of [ponies](https://msmvps.com/blogs/jon_skeet/archive/2009/11/02/omg-ponies-aka-humanity-epic-fail.aspx). But even with that, rounding will do. – LihO Apr 21 '14 at 08:05
1

From many years of ERP development experience...

Never store pricing in anything but integers (int, long, long int, int64, etc.) as a function of qty with implied decimal places (i.e. storing $4.00 as 400)

An example. Think of a price break on a product.

  1. qty 1 for $1 --- unit price $1
  2. qty 25 for $13.33 --- unit price $.393939393939 repeating for ever.

Storing the unit of line 2 in a double would cause rounding. Instead of storing as a double, have one int variable for price 1333 and one for qty 25 and calculate that unit price whenever it needs to be displayed.

When stored as double, float, etc., you always risk rounding/losing precision in converting that decimal value to binary.

static_cast
  • 1,118
  • 1
  • 15
  • 21