c++ - 具有 C++ pi近似的不同输出

  显示原文与译文双语对照的内容
0 0

可能重复:
极大不同输出 C++ 近似

在我的64位 ubuntu计算机上,下面的代码按预期工作,并返回两个算法的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 0

问题是 pow 返回了 double,它在低端处失去了精度。 转换为 % 运算符的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

修复是要改变 x = (long int) (pow(x, 2)) % M;x = x * x % Mlong int 中执行所有算术运算。 注意,由于未定义的溢出是未定义的,这仍然是不正确的;更正确的是使用 unsigned long

原作者:
0 0

BBS() 中的long 导致生成相同的"随意"数。

返回 pow 函数的返回值,它太大,无法在你的计算机类型中表示。 当对 long 进行转换时,会产生未定义的行为。 未定义行为的一个特定效果可以能是转换为 0x80000000 或者 0x7fffffff的结果,因这里最终使用相同的数字序列。

原作者:
0 0

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

一个 32位 int的值最高 2 ^31-1.x^2的值大于。

...