2017-01-10 25 views
3

10^-15 ~ 10^-25의 매우 작은 숫자를 사용하는 코드를 다루고 있습니다. 나는 doublelong double을 사용해 보았습니다. 그러나 0.0000000000000000000010으로 반올림되거나 0.00000000000000002 같은 숫자가 0.00000000000000001999999999999으로 표시되면서 잘못된 대답을 얻습니다.C++ 매우 작은 부동 소수점 숫자, preciscion

1/1000000의 작은 부분만으로도 최종 답변에 큰 차이가 나기 때문에 적절한 수정 사항이 있습니까?

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 

을하지만, 내가 얻을 출력은 다음과 같습니다 :

#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; 
} 

예상 출력해야 내가 double, long double 심지어 boost_dec_float을 시도

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 

,하지만 난 얻을 출력은 비슷한.

+0

구조체를 숫자로 나타내는 구조체를 만듭니다. 기하 급수적으로 짧고, 나머지는 두 배입니다. 그런 작은 숫자로 작업하지 않도록 단위를 변경 하시겠습니까? – UKMonkey

+3

나는 이것이 중복 적이라고 주장 할 것이다. 영업 담당자는 무슨 일이 일어나고 있는지 정확하게 알고 정확성을 높이기위한 해결책을 요구하고 있습니다. – SingerOfTheFall

+1

그래서 문제는'3 * pow (10, -14)'가 0.000000000000030000000000000000이 아닌 0.000000000000029999999999999998로 표시된다는 것입니다. 그것은 거의 double의 정밀도 한계에 있습니다. –

답변

0

숫자가 정확하게 2 진수로 표현 될 수없고 특정 각도로 반올림되기 때문에 이러한 현상이 발생합니다.

이제 태그를 boost 태그로 태그 했으므로 부스트가 원하는대로 정확하게 boost.multiprecision이됩니다. 최대 50 자리의 10 진수까지 정확한 계산을 보장하는 데이터 유형 cpp_dec_float_50을 제공합니다. 그것은 다른 어떤 유형으로 사용 : 문서를 높일 따르면

typedef boost::multiprecision::cpp_dec_float_50 value_type; 

value_type v1 = 1; 
value_type v2 = 3; 

value_type v3 = v1/v2; 

, 이것은 출력이 보장되는 경우에만 정확한 비트 :

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; 
+0

정확한 목표에 따라 이성도 흥미로울 수 있습니다. –

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); 

문제는 powdouble 버전의 롱 버전이 아니라 긴 버전 일 것입니다. 인수 중 하나를 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); 
+0

인텔 하드웨어에서 10 진수 10 진수 5 ~ 6자를 추가로 구입할 수 있습니다. –