39

Is there a way to use decimal data types such as decimal32, decimal64 or decimal128in my C++ programs?

fpiro07
  • 817
  • 1
  • 11
  • 18
  • 1
    C++ doesn't have any decimal types built-in. You'll need a 3rd-party library. – Cory Nelson Dec 31 '12 at 00:11
  • 1
    Yeah I know that, do you know a library which can do that? – fpiro07 Dec 31 '12 at 00:12
  • 1
    We are currently using this implementation which is working well http://sourceforge.net/projects/stddecimal/ – Drew Jun 07 '13 at 23:15
  • There is also the [Bloomberg bde](https://github.com/bloomberg/bde/blob/04a94fe1321b739eff5bc7dd221f89c6ab885304/groups/bdl/bdldfp/bdldfp_decimal.h) library which has [bdldfp_decimal.h](https://github.com/bloomberg/bde/blob/04a94fe1321b739eff5bc7dd221f89c6ab885304/groups/bdl/bdldfp/bdldfp_decimal.h) and [bdldfp_decimalutil.h](https://github.com/bloomberg/bde/blob/04a94fe1321b739eff5bc7dd221f89c6ab885304/groups/bdl/bdldfp/bdldfp_decimalutil.h). – nonsensickle Sep 25 '19 at 11:23

5 Answers5

30

The classes from the Decimal TR are not implemented for all compilers. Some compilers, e.g., gcc, implement the C Decimal TR and provide the corresponding extensions in C++, too. In the past there was an open source implementation for the C++ Decimal TR available but I failed to locate it. If your compiler doesn't support the decimal types, your best option is probably to create a wrapper for IBM's decNumber library.

To improve the situation in the future of C++, I have created a plan to update the TR and I'm going to turn the current TR into a complete proposal ready for the next C++ committee meeting (in April in Bristol), trying to get it adopted into the C++ standard, possibly into the revision planned for 2014. The implementation I have is part of my regular work and it isn't up to me to decide whether it is can be made available publically although there is some hope that it can be open sourced at some point.

Dietmar Kühl
  • 141,209
  • 12
  • 196
  • 356
  • I'm quite a newbie, so don't judge me if I don't understand well... I saw that gcc has this library to implement the Decimal TR: http://gcc.gnu.org/libstdc++/ Do you know how can I use it in my programs? – fpiro07 Dec 31 '12 at 14:10
  • @fpiro07, if you use the G++ compiler then libstdc++ (and its included implementation of the decimal extensions) are available automatically. – Jonathan Wakely Dec 31 '12 at 18:46
  • 5
    The decimals used by gcc are **not** in the library! There are certainly no decimal classes in libstdc++. The logic is built into the compiler. If you use gcc you can configure it when building gcc to include decimal support (by default it isn't included). If use clang or a gcc without decimal support enabled, you win't get decimal support from gcc or its libstdc++. – Dietmar Kühl Dec 31 '12 at 19:23
  • 1
    Dietmar, can you provide an update now that the April meeting has taken place? – jwatt May 06 '13 at 13:50
  • @jwatt: For various reasons I didn't manage to get a paper ready for the Bristol meeting (aside from time also the fact that C started to work on the topic again and that it wouldn't make into C++2014 anyway). The updated plan is to update the TR and target C++2017... – Dietmar Kühl May 06 '13 at 21:23
16

You can use easy to use header-only solution for C++ with templates: https://github.com/vpiotr/decimal_for_cpp

Notice that this is not a *Big*Decimal class; it is limited to 64 bits' worth of "mantissa" digits.

[taken from link]

  #include "decimal.h"

  using namespace dec;

  // the following declares currency variable with 2 decimal points
  // initialized with integer value (can be also floating-point)
  decimal<2> value(143125);

  // to use non-decimal constants you need to convert them to decimal
  value = value / decimal_cast<2>(333.0);

  // output values
  cout << "Result is: " << value << endl;
  // this should display something like "429.80"

  // to mix decimals with different precision use decimal_cast
  decimal<6> exchangeRate(12.1234);
  value = decimal_cast<2>(decimal_cast<6>(value) * exchangeRate);

  cout << "Result 2 is: " << value << endl;
  // this should display something like "5210.64"

  cout << "Result 2<6> is: " << decimal_cast<6>(value) << endl;
  // this should display something like "5210.640000"
Quuxplusone
  • 19,419
  • 5
  • 72
  • 137
Piotr
  • 211
  • 3
  • 2
4

use an int32 or int64, and (manually) shift the decimal point to where you want it to be. If you're measuring dollars, for example, just measure cents instead and display the value differently. simple!

gbjbaanb
  • 49,287
  • 10
  • 99
  • 143
  • 13
    This approach works if you actually have one specific scale you need to support. If you need to deal with a wide variety of scales (government dept on the high end and foreign exchange or interest rates at the other end) even using `int64_t` doesn't give you enough digits for a common scale. The simple solution works for simple uses but fails at least for some applications. – Dietmar Kühl Dec 31 '12 at 00:54
  • Please notice that 64 bits of mantissa, even if you use centicents, gives you a maximum of 9e15 for the largest integer number you can store. This is still a *huge* number (even for a government debt ;-) – xryl669 Jul 15 '19 at 13:23
  • This is called fixed point arithmetic and there are libraries like [CNL](https://github.com/johnmcfarlane/cnl) that offer you this in C++. IIRC there was the proposal [P0037R5](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0037r5.html) for standardization as well, but I'm not sure of its current status. In C this is introduced by the [Embeded C extensions](https://en.wikipedia.org/wiki/Embedded_C) according to Wikipedia. Not a bad idea, if it suits the domain, but I think the question asks something different. – nonsensickle Sep 25 '19 at 11:34
1

Boost has cpp_dec_float as well. That's probably the best solution until it's adopted into the standard.

https://www.boost.org/doc/libs/1_68_0/libs/multiprecision/doc/html/boost_multiprecision/tut/floats/cpp_dec_float.html

EDIT: This library uses floating point values in the implementation so is not a true decimal math library IMO.

  • got artifacts with this. after some time adding and removing small numbers (to: typedef boost::multiprecision::number > decimal; type variable), started to get 5e-35.. instead of 0. not sure what I did wrong. (but decimal_for_cpp worked.) – Shimon Doodkin Oct 04 '20 at 22:11
  • 1
    Thanks for pointing that out. Completely my fault for assuming the implementation. It is floating point types underneath. So used to decimal types in other areas to not use floating point values, I _assumed_ this was the same. Live and learn. – David Bradley Oct 05 '20 at 17:00
0

gcc/clang (usually) come with their own floating point decimal implementations, if your distro decides to compile them into whatever gcc/clang version they offer (not the case for some arm distros I tried out). This is why you sometimes need a custom decimal type implementation. Try mine for ideas (tested on i586 all the way to aarch64).

user1095108
  • 12,675
  • 6
  • 43
  • 96