2011-11-11 12 views
2

疑似ランダム関数をC++からC#に変換しようとしていますが、正しい値が返されないようです。その重要なのは、暗号化に一貫したセットを使用するので、乱数だけを使用することはできません。C++とCの間の一貫性のない疑似ランダム#

これはC++の関数です。

int get_pseudo_rand() 
{ 
    return(((_last_rand = _last_rand * 214013L 
    + 2531011L) >> 16) & 0x7fff); 
} 

が、これが私のC#の代替

int get_pseudo_rand() 
{ 
    return (((_last_rand = (_last_rand * 214013 + 2531011) >> 16) & 0x7fff)); 
} 

#S long型が8バイトであるCに対し、C#のS intデータ型は、C++ long型のような4バイトであるので、私はLSは削除されます。

シードから関数が初めて実行されるとき、答えはC++バージョンと一貫していますが、それは発散し始めます。

アイデア?

+2

では使用++ C++コードはどこかかっこが欠落しています。また、 '_last_rand'が各言語でどのような型かを明確にすることができます。可能であれば、使用しているシードと各プラットフォームの最初の2つの乱数を使用します(C++では、その型のサイズをpaltformに入れます)。 –

+0

確かに、シードは1274653591で、正しく設定されています。 C++コードでは、最初の2つの答えは28818と20295です。これは正しいです。 C#では、最初の2つの結果は28818と28610です。_last_randは両方の言語でint(4バイト)です。私は32ビットのプログラムを使用しているので、intの長さとC++の長さは両方とも4バイトでなければなりません。 (括弧が欠落していると計算には意​​味がありません) – Steve

+2

一時変数を使用すると、意図が明確になり、ここで見つけたようにエラーが発生しにくくなります。また、良いコンパイラ(ジッタ)*はそれを最適化する必要があります。 –

答えて

9

2つのステートメントをその意味を変える別の方法でかっこにしました。 C++コードが_last_randに更新され、結果が右シフトされた場合、C#コードは、_last_randを更新する前に右シフトを実行します。私は違いをより明白にするために、以下のステートメントを並べています。

C++:

return (((_last_rand = _last_rand * 214013L + 2531011L) >> 16) & 0x7fff); 

のC#:

return (((_last_rand = (_last_rand * 214013 + 2531011) >> 16) & 0x7fff)); 
+0

+1確認済みです。店の前にシフトすると、私は1組の答えを得る。店の後にシフトすると、私はもう一方を手に入れます。この違いが原因です。 –

+0

はい、それはうまくいくようです。ありがとう – Steve

+1

@スティーブ:私は、 'C++'コードがもっと正しいと思っていると強調したいと思います。 __before__を右シフトして変数を更新すると、「ランダム」ビットが繰り返しごとに切り捨てられます。 – Blastfurnace

0

問題は、あなたが_last_rand店28818最初の後にあなたのコードで... _last_randで異なる値を格納することにつながるdifferentylを括弧しているということですC++コードで1888663550の値を返します。これは、>>の前、そして&の前の値です。したがって、Cと同じ動作を実現するために...

上のセカンドランから分岐startes C#

return (((_last_rand = _last_rand * 214013 + 2531011) >> 16) & 0x7fff); 
関連する問題