4

我正在处理一个使用非常少量的 10^-15 到 10^-25 的代码。我尝试使用doublelong double但我得到了错误的答案,因为要么被0.000000000000000000001四舍五入,要么0像.0.000000000000000020.00000000000000001999999999999

由于即使是 1/1000000 的一小部分也会对我的最终答案产生巨大影响,是否有适当的解决方法?

#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <iomanip>

using namespace std;

int main()
{
    double  sum, a, b, c,d;
    a=1;
    b=1*pow(10,-15);
    c=2*pow(10,-14);
    d=3*pow(10,-14);
    sum=a+b+c+d;
    cout<<fixed;
    cout<<setprecision(30);
    cout<<" a   : "<<a<<endl<<" b   : "<<b<<endl<<" c   : "<<c<<endl
        <<" d   : "<<d<<endl; 
    cout<<" sum : "<<sum<<endl<<endl;
    a=a/sum;
    b=b/sum;
    c=c/sum;
    d=d/sum;
    sum=a+b+c+d;
    cout<<" a   : "<<a<<endl<<" b   : "<<b<<endl<<" c   : "<<c<<endl
        <<" d   : "<<d<<endl; 
    cout<<" sum2: "<<sum<< endl;
    return 0;
}

预期的输出应该是:

a   : 1.000000000000000000000000000000
b   : 0.000000000000001000000000000000
c   : 0.000000000000020000000000000000
d   : 0.000000000000030000000000000000
sum : 1.000000000000051000000000000000

a   : 1.000000000000000000000000000000
b   : 0.000000000000001000000000000000
c   : 0.000000000000020000000000000000
d   : 0.000000000000030000000000000000
sum1: 1.000000000000051000000000000000

但是,我得到的输出是:

a   : 1.000000000000000000000000000000
b   : 0.000000000000001000000000000000
c   : 0.000000000000020000000000000000
d   : 0.000000000000029999999999999998
sum : 1.000000000000051100000000000000

a   : 0.999999999999998787999878998887
b   : 0.000000000000000999999997897899
c   : 0.000000000000019999999999999458
d   : 0.000000000000029999999999996589
sum1: 0.999999999999989000000000000000

我试过了doublelong double甚至boost_dec_float,但我得到的输出是相似的。

4

2 回答 2

3

正如您所注意到的,发生这种情况是因为数字无法以二进制准确表示,并且在一定程度上四舍五入。

现在,既然你用boosttag 标记了这个,boost 就有了boost.multiprecision,它完全符合你的要求。它提供cpp_dec_float_50的数据类型可确保精确计算多达 50 个十进制数字。它用作任何其他类型:

typedef boost::multiprecision::cpp_dec_float_50 value_type;

value_type v1 = 1;
value_type v2 = 3;

value_type v3 = v1 / v2;

根据 boost doc,这保证只输出精确的位:

cpp_dec_float_50 seventh = cpp_dec_float_50(1) / 7;
cpp_dec_float_50 circumference = boost::math::constants::pi<cpp_dec_float_50>() * 2 * seventh;
std::cout.precision(std::numeric_limits<cpp_dec_float_50>::digits10);
std::cout << circumference << std::endl;
于 2017-01-10T10:47:04.287 回答
0

我打赌你在写:

long double  sum, a, b, c,d;
a=1;
b=1*pow(10,-15);
c=2*pow(10,-14);
d=3*pow(10,-14);

麻烦的是,这pow将是 pow 的双重版本 - 而不是长的双重版本。您需要将其中一个参数强制为 long double:

long double  sum, a, b, c,d;
a=1;
b=1*pow(10.0L,-15);
c=2*pow(10.0L,-14);
d=3*pow(10.0L,-14);
于 2017-01-10T10:54:50.853 回答