5

この投稿がうんざりするほど初心者の性質を持っていることをお許しください。しかし、パソコンで C++ と R でプログラミングをしている方に質問があります。

質問:以下の 2 つのプログラムから生成されるこれらの乱数が等しくないのはなぜですか? また、この問題を解決するにはどうすればよいですか?

  1. まず、 R プログラムでlocal関数と演算子を誤用したと思われます。<<-
  2. 第二に、浮動精度の問題であると思われます。2 つのプログラムの違いがすぐにはわからないので、この問題にどう対処すればよいかわかりません。

C++ でのすべての計算をdouble/ float(偶数long double) にキャストしfmod、モジュラス演算子の代わりに%: 異なる出力を使用してみましたが、R の出力とはまだ似ていません。それが重要かどうかはわかりませんが、 G++ コンパイラを使用して C++ コードをコンパイルしていることを付け加えたいと思います。

アルゴリズム:次のアルゴリズムは、標準的なパーソナル コンピュータで使用できます。3つのワードジェネレータを並行して使用することが提案されました。

  • m k = 171 m k-1 (mod 30269)
  • m' k = 172 m' k-1 (mod 30307)
  • m'' k = 172 m'' k-1 (mod 30323)

小数部分を疑似乱数として使用する

  • g k = { m k / 30269 + m' k / 30307 + m'' k / 30323}

初期値m 0 = 5、m' 0 = 11、およびm'' 0 = 17 を使用しました。

プログラム: C++ で次のプログラムがあります。

//: MC:Uniform.cpp
// Generate pseudo random numbers uniformly between 0 and 1
#include <iostream>
#include <math.h> // For using "fmod()"
using namespace std;

float uniform(){
    // A sequence of initial values
    static int x = 5;
    static int y = 11;
    static int z = 17;

    // Some integer arithmetic required
    x = 171 * (x % 177) - 2 * (x / 177);
    y = 172 * (x % 176) - 35 * (y / 176);
    z = 170 * (x % 178) - 63 * (z / 178);

    /* If both operands are nonnegative then the
    remainder is nonnegative; if not, the sign of
    the remainder is implementation-defined. */
    if(x < 0)
        x = x + 30269;
    if(y < 0)
        y = y + 30307;
    if(z < 0)
        z = z + 30323;

    return fmod(x / 30269. + y / 30307. + z / 30323., 1.);
}

int main(){
    // Print 5 random numbers
    for(int i = 0; i < 5; i++){
        cout << uniform() << ", ";
    }               
}///:~

プログラムはコードで終了し、次を出力します。

0.686912, 0.329174, 0.689649, 0.753722, 0.209394,

次のようなRのプログラムもあります。

## Generate pseudo random numbers uniformly between 0 and 1
uniform <- local({
    # A sequence of initial values
    x = 5
    y = 11
    z = 17

    # Use the <<- operator to make x, y and z local static 
    # variables in R.
    f <- function(){
        x <<- 171 * (x %% 177) - 2 * (x / 177)
        y <<- 172 * (y %% 176) - 35 * (y / 176)
        z <<- 170 * (z %% 178) - 63 * (z / 178)

        return((x / 30269. + y / 30307. + z / 30323.)%%1.)
    }
})

# Print 5 random numbers
for(i in 1:5){
    print(uniform())
}

このプログラムもコードで終了し、出力を生成します

[1] 0.1857093
[1] 0.7222047
[1] 0.05103441
[1] 0.7375034
[1] 0.2065817

事前に感謝します。

4

2 に答える 2

5

%/%R コードには、さらにいくつかの 's (整数除算)が必要です。デフォルトでは、R の数値変数は整数ではなく浮動小数点であることを思い出してください。/非整数の商による通常の除算も同様です。xまた、負の/ y/を扱う部分も省略していますz

f <- function(){
    x <<- 171 * (x %% 177) - 2 * (x %/% 177)
    y <<- 172 * (y %% 176) - 35 * (y %/% 176)
    z <<- 170 * (z %% 178) - 63 * (z %/% 178)

    if(x < 0)
        x <<- x + 30269;
    if(y < 0)
        y <<- y + 30307;
    if(z < 0)
        z <<- z + 30323;

    return((x / 30269. + y / 30307. + z / 30323.)%%1)
}

これらの変更を行った後、結果に深刻な問題はないようです。100000 回のランダム描画のクイック ヒストグラムは非常に均一に見え、自己相関は見られません。ただし、C++の結果とはまだ一致しません....

于 2013-07-16T16:11:10.980 に答える
5

C++ コードに単純なコピー/貼り付けエラーがあります。これ

x = 171 * (x % 177) -  2 * (x / 177);
y = 172 * (x % 176) - 35 * (y / 176);
z = 170 * (x % 178) - 63 * (z / 178);

これであるべきです。

x = 171 * (x % 177) -  2 * (x / 177);
y = 172 * (y % 176) - 35 * (y / 176);
z = 170 * (z % 178) - 63 * (z / 178);
于 2013-07-16T16:35:57.067 に答える