I'm looking for a C++ class that can do decimal floating point arithmetic. Looking through http://speleotrove.com/decimal/ there are links to all sorts of classes that people have written and not maintained. Digging through the decNumber++ stuff led me to some emails showing that GCC will eventually support this functionality. (Formally known as ISO/IEC TR 24733)
我正在寻找一个可以进行十进制浮点运算的C ++类。通过http://speleotrove.com/decimal/可以看到人们编写和未维护的各种类的链接。挖掘decNumber ++的东西让我看到一些电子邮件,表明GCC最终会支持这个功能。 (正式名称为ISO / IEC TR 24733)
I'm looking for something I can use as a drop-in replacement for float or double, something that other people are using in their own projects. Hopefully open source.
我正在寻找一些我可以用作浮动或双重替代品的东西,这是其他人在他们自己的项目中使用的东西。希望开源。
Thanks!
EDIT: I should point out that I'm trying to use this to represent prices. So I need EXACT decimals, not HUGE decimals.
编辑:我应该指出,我正试图用它来代表价格。所以我需要精确的小数,而不是巨大的小数。
8 个解决方案
#1
14
There exists a huge library called GMP (GNU multiple precision library) which supports this and also has C++ bindings, though to be honest the C++ interface is a bit wonky and outdated.
存在一个名为GMP(GNU多精度库)的巨大库,它支持这个并且还有C ++绑定,但老实说C ++接口有点不稳定和过时。
An example from the documentation, the following creates a float called f
with at least 500 bits of precision:
文档中的一个示例,下面创建一个名为f的浮点数,其精度至少为500位:
mpf_class f(1.5, 500);
#2
8
Take your pick. There are a bunch of them out there. For instance, you can consult the list on Wikipedia.
随便挑选。那里有很多人。例如,您可以查阅*上的列表。
#3
4
If you need to do operations with HUGE decimal values I would suggest you to use http://gmplib.org/ library. I've used it a lot with C and C++.
如果您需要使用HUGE十进制值进行操作,我建议您使用http://gmplib.org/ library。我在C和C ++中经常使用它。
#4
4
The question is a bit old, but for other people that have the same need : Boost.multiprecision is probably what you're looking for.
这个问题有点旧,但对于其他有相同需求的人来说:Boost.multiprecision可能正是你所寻找的。
It's an arbitrary precision library that can handle 10-based decimals.
它是一个可以处理基于10的小数的任意精度库。
#5
3
Use GMP and store everything as cents. If you know that you won't pass 2^32 cents (42.949673 million dollars) use a 32 bit unsigned int (or use a 64 bit unsigned int) and keep it simple.
使用GMP并将所有内容存储为美分。如果你知道你不会通过2 ^ 32美分(42.949673美元)使用32位无符号int(或使用64位无符号int)并保持简单。
#6
1
Probably "MAPM, A Portable Arbitrary Precision Math Library in C" is what you are looking for. It also includes C++ Wrappers:
可能是“MAPM,C中的便携式任意精度数学库”正是您所需要的。它还包括C ++ Wrappers:
#7
1
I may be too late for this but would 128bit decimals work? These have been accepted into C++ and at least gcc has them since gcc-4.5 (we're starting 4.9 now:
我可能为时已晚,但128位小数是否有效?这些已被C ++接受,至少gcc从gcc-4.5开始就拥有它们(我们现在开始4.9:
#include <iostream>
#include <decimal/decimal>
using namespace std;
int main()
{
{
std::decimal::decimal32 dn(.3), dn2(.099), dn3(1000), dn4(201);
dn-=dn2;
dn*=dn3;
cout << "decimal32 = " << (dn==dn4) << " : " << decimal32_to_double(dn) << endl;
}
{
std::decimal::decimal64 dn(.3), dn2(.099), dn3(1000), dn4(201);
dn-=dn2;
dn*=dn3;
cout << "decimal64 = " << (dn==dn4) << " : " << decimal64_to_double(dn) << endl;
}
{
std::decimal::decimal128 dn(.3), dn2(.099), dn3(1000), dn4(201);
dn-=dn2;
dn*=dn3;
cout << "decimal128 = " << (dn==dn4) << " : " << decimal128_to_double(dn) << endl;
}
return 0;
}
Note there is decimal32 equal in size to float, decimal64 equal in size to most double. So decimal128 is pretty big. From Wikipedia: Decimal128 supports 34 decimal digits of significand and an exponent range of −6143 to +6144, i.e. ±0.000000000000000000000000000000000×10−6143 to ±9.999999999999999999999999999999999×106144. (Equivalently, ±0000000000000000000000000000000000×10−6176 to ±9999999999999999999999999999999999×106111.)
注意,decimal32的大小等于decimal,decimal64的大小等于大多数double。所以decimal128非常大。来自*:Decimal128支持有效数的34位十进制数和指数范围-6143至+6144,即±0.000000000000000000000000000000000×10-6143至±9.99999999999999999999999999999999999×106144。 (等效地,±0000000000000000000000000000000000×10-6176至±9999999999999999999999999999999999×106111。)
The mpfr library is arbitrary precision binary floating point - not arbitrary precision decimal. There is a difference.
mpfr库是任意精度二进制浮点 - 不是任意精度十进制。它们是有区别的。
#8
1
Here is an implementation of BCMath PHP to C++. There are two versions, one for Qt and the other for use only STL.
这是BCMath PHP到C ++的实现。有两个版本,一个用于Qt,另一个仅用于STL。
Source: https://github.com/DesarrollosCuado/BCMath-for-Cpp
BCMath::bcscale(4); //Num Decimals
BCMath test("-5978");
test^=30; //Pow, only integers. Not work decimals.
std::cout<<"Result BigDecimal 1: "<<test.toString().c_str()<<std::endl;
test-=1.23; //sub
std::cout<<"Result BigDecimal 2: "<<test.toString().c_str()<<std::endl;
test*=1.23; //mul
std::cout<<"Result BigDecimal 3: "<<test.toString().c_str()<<std::endl;
test*=-1.23; //mul
std::cout<<"Result BigDecimal 4: "<<test.toString().c_str()<<std::endl;
BCMath::bcscale(70); //Num Decimals
BCMath randNum("-5943534512345234545.8998928392839247844353457");
BCMath pi("3.1415926535897932384626433832795028841971693993751058209749445923078164062862");
BCMath result1 = randNum + pi;
BCMath result2 = randNum - pi;
BCMath result3 = randNum * pi;
BCMath result4 = randNum / pi;
std::cout<<"Result Super Precision 1: "<<result1.toString().c_str()<<std::endl;
std::cout<<"Result Super Precision 2: "<<result2.toString().c_str()<<std::endl;
std::cout<<"Result Super Precision 3: "<<result3.toString().c_str()<<std::endl;
std::cout<<"Result Super Precision 4: "<<result4.toString().c_str()<<std::endl;
//Other example
BCMath::bcscale(4); //Num Decimals
std::cout<<"Other 1: "<<BCMath::bcmul("1000000.0134", "8.0234").c_str()<<std::endl;
std::cout<<"Other 2: "<<BCMath::bcadd("1000000.0134", "8.0234").c_str()<<std::endl;
std::cout<<"Compare 1: "<<BCMath::bccomp("1", "2")<<std::endl;
std::cout<<"Compare 2: "<<BCMath::bccomp("1.00001", "1", 3)<<std::endl;
std::cout<<"Compare 3: "<<BCMath::bccomp("1.00001", "1", 5)<<std::endl;
std::cout<<"Compare 4: "<<(BCMath("1")< BCMath("2"))<<std::endl;
std::cout<<"Compare 5: "<<(BCMath("1")<=BCMath("2"))<<std::endl;
std::cout<<"Compare 6: "<<(BCMath("1")> BCMath("2"))<<std::endl;
std::cout<<"Compare 7: "<<(BCMath("1")>=BCMath("2"))<<std::endl;
std::cout<<"Compare 8: "<<(BCMath("2")< BCMath("2"))<<std::endl;
std::cout<<"Compare 9: "<<(BCMath("2")<=BCMath("2"))<<std::endl;
std::cout<<"Compare 10: "<<(BCMath("2")> BCMath("2"))<<std::endl;
std::cout<<"Compare 11: "<<(BCMath("2")>=BCMath("2"))<<std::endl;
std::cout<<"Round 1: "<<BCMath::bcround("123.01254").c_str()<<std::endl;
std::cout<<"Round 2: "<<BCMath::bcround("-123.01254", 3).c_str()<<std::endl;
std::cout<<"Round 3: "<<BCMath::bcround("123.01254", 2).c_str()<<std::endl;
pi.round(3);
std::cout<<"Round 4: "<<pi.toString().c_str()<<std::endl;
BCMath part1("-.123");
BCMath part2(".123");
BCMath part3("123");
std::cout<<"Int part 1: "<<part1.getIntPart().c_str()<<std::endl;
std::cout<<"Dec part 1: "<<part1.getDecPart().c_str()<<std::endl;
std::cout<<"Int part 2: "<<part2.getIntPart().c_str()<<std::endl;
std::cout<<"Dec part 2: "<<part2.getDecPart().c_str()<<std::endl;
std::cout<<"Int part 3: "<<part3.getIntPart().c_str()<<std::endl;
std::cout<<"Dec part 3: "<<part3.getDecPart().c_str()<<std::endl;
Result:
Result BigDecimal 1: 198005530669253749533290222782634796336450786581284861381777714804795900171726938603997395193921984842256586113024
Result BigDecimal 2: 198005530669253749533290222782634796336450786581284861381777714804795900171726938603997395193921984842256586113022.7700
Result BigDecimal 3: 243546802723182111925946974022640799493834467494980379499586589209898957211224134482916796088524041355975600919018.0071
Result BigDecimal 4: -299562567349513997668914778047848183377416395018825866784491504728175717369805685413987659188884570867849989130392.1487
Result Super Precision 1: -5943534512345234542.7583001856941315459727023167204971158028306006248941790250554076921835
Result Super Precision 2: -5943534512345234549.0414854928737180228979890832795028841971693993751058209749445923078164
Result Super Precision 3: -18672164360341183116.9114783895073349180904753962992796943871920962352436079118338887287186
Result Super Precision 4: -1891885794154043400.2804849527556211973567525043250278948318788149660700494315139982452600
Other 1: 8023400.1075
Other 2: 1000008.0368
Compare 1: -1
Compare 2: 0
Compare 3: 1
Compare 4: true
Compare 5: true
Compare 6: false
Compare 7: false
Compare 8: false
Compare 9: true
Compare 10: false
Compare 11: true
Round 1: 123.0125
Round 2: -123.013
Round 3: 123.01
Round 4: 3.142
Int part 1: -0
Dec part 1: 123
Int part 2: 0
Dec part 2: 123
Int part 3: 123
Dec part 3: 0
#1
14
There exists a huge library called GMP (GNU multiple precision library) which supports this and also has C++ bindings, though to be honest the C++ interface is a bit wonky and outdated.
存在一个名为GMP(GNU多精度库)的巨大库,它支持这个并且还有C ++绑定,但老实说C ++接口有点不稳定和过时。
An example from the documentation, the following creates a float called f
with at least 500 bits of precision:
文档中的一个示例,下面创建一个名为f的浮点数,其精度至少为500位:
mpf_class f(1.5, 500);
#2
8
Take your pick. There are a bunch of them out there. For instance, you can consult the list on Wikipedia.
随便挑选。那里有很多人。例如,您可以查阅*上的列表。
#3
4
If you need to do operations with HUGE decimal values I would suggest you to use http://gmplib.org/ library. I've used it a lot with C and C++.
如果您需要使用HUGE十进制值进行操作,我建议您使用http://gmplib.org/ library。我在C和C ++中经常使用它。
#4
4
The question is a bit old, but for other people that have the same need : Boost.multiprecision is probably what you're looking for.
这个问题有点旧,但对于其他有相同需求的人来说:Boost.multiprecision可能正是你所寻找的。
It's an arbitrary precision library that can handle 10-based decimals.
它是一个可以处理基于10的小数的任意精度库。
#5
3
Use GMP and store everything as cents. If you know that you won't pass 2^32 cents (42.949673 million dollars) use a 32 bit unsigned int (or use a 64 bit unsigned int) and keep it simple.
使用GMP并将所有内容存储为美分。如果你知道你不会通过2 ^ 32美分(42.949673美元)使用32位无符号int(或使用64位无符号int)并保持简单。
#6
1
Probably "MAPM, A Portable Arbitrary Precision Math Library in C" is what you are looking for. It also includes C++ Wrappers:
可能是“MAPM,C中的便携式任意精度数学库”正是您所需要的。它还包括C ++ Wrappers:
#7
1
I may be too late for this but would 128bit decimals work? These have been accepted into C++ and at least gcc has them since gcc-4.5 (we're starting 4.9 now:
我可能为时已晚,但128位小数是否有效?这些已被C ++接受,至少gcc从gcc-4.5开始就拥有它们(我们现在开始4.9:
#include <iostream>
#include <decimal/decimal>
using namespace std;
int main()
{
{
std::decimal::decimal32 dn(.3), dn2(.099), dn3(1000), dn4(201);
dn-=dn2;
dn*=dn3;
cout << "decimal32 = " << (dn==dn4) << " : " << decimal32_to_double(dn) << endl;
}
{
std::decimal::decimal64 dn(.3), dn2(.099), dn3(1000), dn4(201);
dn-=dn2;
dn*=dn3;
cout << "decimal64 = " << (dn==dn4) << " : " << decimal64_to_double(dn) << endl;
}
{
std::decimal::decimal128 dn(.3), dn2(.099), dn3(1000), dn4(201);
dn-=dn2;
dn*=dn3;
cout << "decimal128 = " << (dn==dn4) << " : " << decimal128_to_double(dn) << endl;
}
return 0;
}
Note there is decimal32 equal in size to float, decimal64 equal in size to most double. So decimal128 is pretty big. From Wikipedia: Decimal128 supports 34 decimal digits of significand and an exponent range of −6143 to +6144, i.e. ±0.000000000000000000000000000000000×10−6143 to ±9.999999999999999999999999999999999×106144. (Equivalently, ±0000000000000000000000000000000000×10−6176 to ±9999999999999999999999999999999999×106111.)
注意,decimal32的大小等于decimal,decimal64的大小等于大多数double。所以decimal128非常大。来自*:Decimal128支持有效数的34位十进制数和指数范围-6143至+6144,即±0.000000000000000000000000000000000×10-6143至±9.99999999999999999999999999999999999×106144。 (等效地,±0000000000000000000000000000000000×10-6176至±9999999999999999999999999999999999×106111。)
The mpfr library is arbitrary precision binary floating point - not arbitrary precision decimal. There is a difference.
mpfr库是任意精度二进制浮点 - 不是任意精度十进制。它们是有区别的。
#8
1
Here is an implementation of BCMath PHP to C++. There are two versions, one for Qt and the other for use only STL.
这是BCMath PHP到C ++的实现。有两个版本,一个用于Qt,另一个仅用于STL。
Source: https://github.com/DesarrollosCuado/BCMath-for-Cpp
BCMath::bcscale(4); //Num Decimals
BCMath test("-5978");
test^=30; //Pow, only integers. Not work decimals.
std::cout<<"Result BigDecimal 1: "<<test.toString().c_str()<<std::endl;
test-=1.23; //sub
std::cout<<"Result BigDecimal 2: "<<test.toString().c_str()<<std::endl;
test*=1.23; //mul
std::cout<<"Result BigDecimal 3: "<<test.toString().c_str()<<std::endl;
test*=-1.23; //mul
std::cout<<"Result BigDecimal 4: "<<test.toString().c_str()<<std::endl;
BCMath::bcscale(70); //Num Decimals
BCMath randNum("-5943534512345234545.8998928392839247844353457");
BCMath pi("3.1415926535897932384626433832795028841971693993751058209749445923078164062862");
BCMath result1 = randNum + pi;
BCMath result2 = randNum - pi;
BCMath result3 = randNum * pi;
BCMath result4 = randNum / pi;
std::cout<<"Result Super Precision 1: "<<result1.toString().c_str()<<std::endl;
std::cout<<"Result Super Precision 2: "<<result2.toString().c_str()<<std::endl;
std::cout<<"Result Super Precision 3: "<<result3.toString().c_str()<<std::endl;
std::cout<<"Result Super Precision 4: "<<result4.toString().c_str()<<std::endl;
//Other example
BCMath::bcscale(4); //Num Decimals
std::cout<<"Other 1: "<<BCMath::bcmul("1000000.0134", "8.0234").c_str()<<std::endl;
std::cout<<"Other 2: "<<BCMath::bcadd("1000000.0134", "8.0234").c_str()<<std::endl;
std::cout<<"Compare 1: "<<BCMath::bccomp("1", "2")<<std::endl;
std::cout<<"Compare 2: "<<BCMath::bccomp("1.00001", "1", 3)<<std::endl;
std::cout<<"Compare 3: "<<BCMath::bccomp("1.00001", "1", 5)<<std::endl;
std::cout<<"Compare 4: "<<(BCMath("1")< BCMath("2"))<<std::endl;
std::cout<<"Compare 5: "<<(BCMath("1")<=BCMath("2"))<<std::endl;
std::cout<<"Compare 6: "<<(BCMath("1")> BCMath("2"))<<std::endl;
std::cout<<"Compare 7: "<<(BCMath("1")>=BCMath("2"))<<std::endl;
std::cout<<"Compare 8: "<<(BCMath("2")< BCMath("2"))<<std::endl;
std::cout<<"Compare 9: "<<(BCMath("2")<=BCMath("2"))<<std::endl;
std::cout<<"Compare 10: "<<(BCMath("2")> BCMath("2"))<<std::endl;
std::cout<<"Compare 11: "<<(BCMath("2")>=BCMath("2"))<<std::endl;
std::cout<<"Round 1: "<<BCMath::bcround("123.01254").c_str()<<std::endl;
std::cout<<"Round 2: "<<BCMath::bcround("-123.01254", 3).c_str()<<std::endl;
std::cout<<"Round 3: "<<BCMath::bcround("123.01254", 2).c_str()<<std::endl;
pi.round(3);
std::cout<<"Round 4: "<<pi.toString().c_str()<<std::endl;
BCMath part1("-.123");
BCMath part2(".123");
BCMath part3("123");
std::cout<<"Int part 1: "<<part1.getIntPart().c_str()<<std::endl;
std::cout<<"Dec part 1: "<<part1.getDecPart().c_str()<<std::endl;
std::cout<<"Int part 2: "<<part2.getIntPart().c_str()<<std::endl;
std::cout<<"Dec part 2: "<<part2.getDecPart().c_str()<<std::endl;
std::cout<<"Int part 3: "<<part3.getIntPart().c_str()<<std::endl;
std::cout<<"Dec part 3: "<<part3.getDecPart().c_str()<<std::endl;
Result:
Result BigDecimal 1: 198005530669253749533290222782634796336450786581284861381777714804795900171726938603997395193921984842256586113024
Result BigDecimal 2: 198005530669253749533290222782634796336450786581284861381777714804795900171726938603997395193921984842256586113022.7700
Result BigDecimal 3: 243546802723182111925946974022640799493834467494980379499586589209898957211224134482916796088524041355975600919018.0071
Result BigDecimal 4: -299562567349513997668914778047848183377416395018825866784491504728175717369805685413987659188884570867849989130392.1487
Result Super Precision 1: -5943534512345234542.7583001856941315459727023167204971158028306006248941790250554076921835
Result Super Precision 2: -5943534512345234549.0414854928737180228979890832795028841971693993751058209749445923078164
Result Super Precision 3: -18672164360341183116.9114783895073349180904753962992796943871920962352436079118338887287186
Result Super Precision 4: -1891885794154043400.2804849527556211973567525043250278948318788149660700494315139982452600
Other 1: 8023400.1075
Other 2: 1000008.0368
Compare 1: -1
Compare 2: 0
Compare 3: 1
Compare 4: true
Compare 5: true
Compare 6: false
Compare 7: false
Compare 8: false
Compare 9: true
Compare 10: false
Compare 11: true
Round 1: 123.0125
Round 2: -123.013
Round 3: 123.01
Round 4: 3.142
Int part 1: -0
Dec part 1: 123
Int part 2: 0
Dec part 2: 123
Int part 3: 123
Dec part 3: 0