2015-11-03 488 views
5

我正在运行物理实验的模拟,所以我需要非常高的浮点精度(超过16位数)。我使用Boost.Multiprecision,但无论如何,我无法获得高于16位数的精度。我运行C++和Eclipse编译器模拟,例如:使用boost lib更高精度的浮点数(高于16位数)

#include <boost/math/constants/constants.hpp> 
#include <boost/multiprecision/cpp_dec_float.hpp> 
#include <iostream> 
#include <limits> 

using boost::multiprecision::cpp_dec_float_50; 

void main() 
{ 
    cpp_dec_float_50 my_num= cpp_dec_float_50(0.123456789123456789123456789); 
    std::cout.precision(std::numeric_limits<cpp_dec_float_50>::digits10); 
    std::cout << my_num << std::endl; 
} 

输出是:

0.12345678912345678379658409085095627233386039733887 
       ^

但它应该是:

0.123456789123456789123456789 

正如你可以看到,16后数字不正确。为什么?

回答

11

你的问题就在这里:

cpp_dec_float_50 my_num = cpp_dec_float_50(0.123456789123456789123456789); 
              ^// This number is a double! 

的编译器不使用任意精度浮点文字,而是使用IEEE-754 双打,具有有限的精度。在这种情况下,最接近double给你写的数字是:

0.1234567891234567837965840908509562723338603973388671875 

而且将它打印到小数点第50确实给你所观察的输出。

你需要的是从字符串构建你的任意精度浮点数,而不是(demo):

#include <boost/math/constants/constants.hpp> 
#include <boost/multiprecision/cpp_dec_float.hpp> 
#include <iostream> 
#include <limits> 

using boost::multiprecision::cpp_dec_float_50; 

int main() { 
    cpp_dec_float_50 my_num = cpp_dec_float_50("0.123456789123456789123456789"); 
    std::cout.precision(std::numeric_limits<cpp_dec_float_50>::digits10); 
    std::cout << my_num << std::endl; 
} 

输出:

0.123456789123456789123456789 
2

问题是编译时C++编译器会将数字转换为双精度(前一段也是learned)。你必须使用特殊的函数来处理更多的小数点。有关示例,请参阅SO上的Boost documentation或其他answers

也就是说,几乎不可能有这样高精度的实际需求。如果你失去了精度,你应该考虑其他浮点算法,而不是盲目地增加小数位数。