2012-11-30 2 views
0

가능한 중복 : 내 64 비트 우분투 컴퓨터에서
Vastly different output C++ monte carlo approximation다른 출력

, 다음 코드는 예상대로 작동하고,와 PI에 대한 근사치를 반환 두 알고리즘. 그러나 32 비트 rhel 3 머신의 코드를 데모해야하는 랩 머신에서 두 번째 알고리즘은 항상 4를 반환하고 이유를 파악할 수 없습니다. 모든 통찰력은 인정 될 것이다.

/* 
* RandomNumber.h 
* 
* 
*  
*/ 

#ifndef RANDOMNUMBER_H_ 
#define RANDOMNUMBER_H_ 

class RandomNumber { 
public: 
RandomNumber() { 
    x = time(NULL); 
    m = pow(2, 31); //some constant value 
    M = 65915 * 7915; //multiply of some simple numbers p and q 
    method = 1; 
} 
RandomNumber(int seed) { 
    x = ((seed > 0) ? seed : time(NULL)); 
    m = pow(2, 31); //some constant value 
    method = 1; //method number 
    M = 6543 * 7915; //multiply of some simple numbers p and q 
} 
void setSeed(long int seed) { 
    x = seed; //set start value 
} 

void chooseMethod(int method) { 
    this->method = ((method > 0 && method <= 2) ? method : 1); //choose one of two method 
} 

long int linearCongruential() { //first generator, that uses linear congruential method 
    long int c = 0; // some constant 
    long int a = 69069; //some constant 
    x = (a * x + c) % m; //solution next value 
    return x; 
} 

long int BBS() { //algorithm Blum - Blum - Shub 
    x = (long int) (pow(x, 2)) % M; 
    return x; 
} 
double nextPoint() { //return random number in range (-1;1) 
    double point; 
    if (method == 1) //use first method 
     point = linearCongruential()/double(m); 
    else 
     point = BBS()/double(M); 
    return point; 
} 
private: 
long int x; //current value 
long int m; // some range for first method 
long int M; //some range for second method 
int method; //method number 
}; 

#endif /* RANDOMNUMBER_H_ */ 

그리고 테스트 클래스 :

#include <iostream> 
#include <stdlib.h> 
#include <math.h> 
#include <iomanip> 
#include "RandomNumber.h" 
using namespace std; 

int main() { 
cout.setf(ios::fixed); 
cout.precision(6); 
RandomNumber random; 
srand((unsigned) time(NULL)); 
cout << "---------------------------------" << endl; 
cout << " Monte Carlo Pi Approximation" << endl; 
cout << "---------------------------------" << endl; 
cout << " Enter number of points: "; 
long int k1; 
cin >> k1; 
cout << "Select generator number: "; 
int method; 
cin >> method; 
random.chooseMethod(method); 
cout << "---------------------------------" << endl; 
long int k2 = 0; 
double sumX = 0; 
double sumY = 0; 
for (long int i = 0; i < k1; i++) { 
    double x = pow(-1, int(random.nextPoint() * 10) % 2) 
      * random.nextPoint(); 
    double y = pow(-1, int(random.nextPoint() * 10) % 2) 
      * random.nextPoint(); 
    sumX += x; 
    sumY += y; 
    if ((pow(x, 2) + pow(y, 2)) <= 1) 
     k2++; 

} 
double pi = 4 * (double(k2)/k1); 
cout << "M(X) = " << setw(10) << sumX/k1 << endl; //mathematical expectation of x 
cout << "M(Y) = " << setw(10) << sumY/k1 << endl; //mathematical expectation of y 
cout << endl << "Pi = " << pi << endl << endl; //approximate Pi 

return 0; 
} 
+0

일반적으로 'long'은 32 비트 아키텍처에서는 32 비트이고 64 비트 아키텍처에서는 64 비트입니다. 아마 당신은 이걸로 잘못하고있는 걸까요? – Angew

+0

@JoachimPileborg 그것은 비슷하지만 답변이 잘못되어 더 이상 값을 설정하는 데 인수를 사용하지 않고 있으며 문제가 여전히 존재합니다. – kqualters

+0

그런 다음 수락 된 답변의 선택을 취소하고 대신 이전 질문을 편집하십시오. 질문을 편집하면 문제가 발생하여 '잡음'에서 손실되지 않습니다. –

답변

0

BBS()에서 long에 절단이 같은 "임의의"번호가 생성됩니다.

추신. pow 함수에서 리턴 값이 너무 커서 시스템의 long 유형으로 표시 할 수 없습니다. long으로 변환 할 때 정의되지 않은 동작이 발생합니다. 정의되지 않은 동작의 한 가지 특수 효과는 변환 결과가 0x80000000 또는 0x7fffffff 일 수 있으므로 같은 번호의 시퀀스로 끝납니다.

+0

@chilll 이걸 좀 더 자세히 설명해 주시겠습니까? – kqualters

+0

위의 예에서 –

1

powdouble을 반환하며, 낮은 쪽에서는 정밀도가 떨어집니다. % 연산자의 경우 long int으로 변환하면 항상 동일한 결과가 반환되므로 RNG 출력은 ​​-60614748로 일정합니다.

x = time(0)     1354284781 
pow(x, 2)     1.83409e+18 0x1.973fdc9dc7787p+60 
(long int) pow(x, 2)  -2147483648 0x80000000 
(long int) pow(x, 2) % M  -60614748 

수정은 long int 내의 모든 연산을 수행 x = x * x % Mx = (long int) (pow(x, 2)) % M;을 변경하는 것이다. 서명 된 오버 플로우는 정의되지 않았으므로 여전히 엄격하게 말하기에주의하십시오. 더 정확한 것은 unsigned long을 사용하는 것입니다.

+0

흥미롭게도이 결과는 4.000에서 3.99480 또는 그 부근의 출력을 계속 변경합니다. – kqualters

+0

@ecatmur 자신이 지적했듯이 아무 일도 일어나지 않을 수 있습니다. 이는 여전히 정의되지 않은 동작을 유발합니다. – chill

0
x = time(0)     1354284781 
pow(x, 2)     1.83409e+18 0x1.973fdc9dc7787p+60 

32 비트 INT는 X^2^31-1의 2 값보다 큰 최대 값을 보유하고있다.

관련 문제