2013-08-30 2 views
0
#include <iostream> 
#include <cmath> 

using namespace std; 

unsigned long long modExp(unsigned long long b, unsigned long long e, unsigned long long m) 
{ 
    unsigned long long remainder; 
    unsigned long long x = 1; 

    while (e != 0) 
    { 
     remainder = e % 2; 
     e= e/2; 

     // These lines 
     if(remainder==1) 
      x=(unsigned long long)fmodl(((long double)x*(long double)b),(long double)m); 
     b=(unsigned long long)fmodl(((long double)b*(long double)b),(long double)m); 
    } 
    return x; 
} 

int main() 
{ 
    unsigned long long lastTen = 0,netSum=0; 
    unsigned long long sec(unsigned long long,unsigned long long); 

    for(int i=1;i<1001;i++) 
    { 
     lastTen = modExp(i,i,10000000000); 
     netSum += lastTen; 
     netSum %= 10000000000; 
     cout << lastTen << endl ; 
    } 

    cout << netSum%10000000000 << endl; 
    cout << sizeof(long double) << endl; 
    return 0; 
} 

이것은 일련의 합계 중 마지막 10 자리를 계산하는 프로그램입니다. 그것은 산술 지수 기법을 사용하여 마지막 10 자리를 계산합니다. 10^9에서 잘 작동합니다. 그러나 10^10에 가면 붕괴됩니다.fmodl - 긴 이중 모듈

더 높은 크기의 데이터 유형을 사용하기 위해 숫자를 long double로 곱하고 곱해서 (다시 long double을 산출합니다)이 숫자에 대한 모듈러스를 취하면 우리는 올바르게 답을 얻을 수 있습니다 . 그러나 나는 똑같은 대답을 다시 일으키는 올바른 대답을 다시 얻지 못했습니다.

내 나는 그래서이 10 개 자리 숫자를 곱한 10 자리 숫자로 많은 수를 얻을 것 moding하고 있기 때문에, 그런 일이

  • 처럼 오래 오래 8 바이트 부호없는 지 확인 생각 것 unsigned long long에 적합하지 않습니다. 따라서 부호없는 long long으로 순환합니다.
  • 위의 점에서 부호없는 long long을 long double (12 바이트)로 변환하고 큰 공간을 가지고 있기 때문에 2 자리 10 자리 숫자의 20 자리 곱

아무도이 논리에 결함이 뭐라고 할 수 있습니까 ??

+0

''main'처럼''modExp' 함수를 제대로 들여 쓰기를 할 수 있습니까? 또한'main'에서'sec' 함수 선언은 무엇입니까? –

+0

예. 코드를 수정했습니다. –

답변

2

공통 long double 구현은 모든 20 자리 10 진수를 정확하게 나타낼 수 없습니다.

long double의 특성은 C++ 표준에 의해 완전히 결정되지 않으며 사용중인 구현을 명시하지 않은 것입니다.

long double의 일반적인 구현 중 하나는 64 비트 유효 숫자를 사용합니다. 12 바이트에 저장 될 수 있지만, 10 개만 사용되며 그 중 16 개는 부호와 지수로 사용되며, significand (명시적인 선행 비트 포함)에 64를 남겨 둡니다.

64 개의 유효수 비트는 약 1.845 • 10 19 인 2 64, 에러없는 최대 정수를 나타낼 수있다. 따라서 모든 20 자리 숫자를 정확하게 나타낼 수는 없습니다.

+0

답변 해 주셔서 감사합니다! 이 문제를 해결할 다른 방법이 있습니까? –