2011-11-11 32 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)); 
} 

我除去LS由於C#小號int數據類型爲4個字節,如C++多頭而C#小號多頭是8個字節。

函數首次從種子運行時,答案與C++版本一致,但隨後開始發散。

任何想法?

+2

的C++代碼的地方缺少一個括號。另外,你能否澄清每種語言中'_last_rand'的類型。 (對於C++,你的平臺上的那種類型的大小。)另外,如果可能的話,你正在使用的種子和每個平臺上的前兩個隨機數。 –

+0

當然,種子是1274653591,並且它的設置都正確。在C++代碼中,前兩個答案是28818和20295.這些都是正確的。在C#中,前兩個結果是28818和28610. _last_rand是兩種語言的int(4字節)。我使用的是32位程序,因此C++中的ints和long的大小都應該是4個字節。 (缺少的括號對計算無關緊要) – Steve

+2

你知道,如果你使用臨時變量,它會使你的意圖更清楚,並且會使得這種錯誤更少地受到你在這裏找到的錯誤的影響。另外,一個好的編譯器(抖動)*應該*優化它。 –

回答

9

您用不同的方式將兩個語句括起來,以改變它們的含義。 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已確認。隨着店面的轉變,我得到了一套答案。隨着店鋪的轉變,我得到了另一個。這說明了差異。 –

+0

是的,這似乎工作。謝謝 – Steve

+1

@Steve:我想強調一下,我認爲'C++'代碼更加正確。如果你右移__before__更新你的變量,那麼每個迭代都會截斷「隨機」位。 – Blastfurnace

0

的問題是,你已經在第一後括號differentyl這導致_last_rand存儲不同的價值觀......你的代碼_last_rand店28818運行...使用C++代碼存儲1888663550,這是值BEFORE >>之前和&之前。因此,startes從第二次運行發散...

要達到相同的行爲在C++中使用C#

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