簡體   English   中英

使用按位&代替模運算符從范圍內隨機采樣整數

[英]Using bitwise & instead of modulus operator to randomly sample integers from a range

我需要從C ++中間隔[LB,UB]的整數均勻分布中隨機抽樣。 為此,我首先使用一個“好的” RN生成器(來自《數字食譜》第三版),該生成器均勻地隨機采樣64位整數; 我們稱之為int64()

使用mod運算符,我可以通過以下方式從[LB,UB]的整數采樣:

LB+int64()%(UB-LB+1);

使用mod運算符的唯一問題是整數除法的慢度。 因此,我嘗試了這里建議的方法,即:

LB + (int64()&(UB-LB))

按位&方法的速度約為3倍。 這對我來說是巨大的,因為我在C ++中進行的模擬之一需要隨機采樣大約2000萬個整數。

但是有一個大問題。 當我分析使用按位&方法采樣的整數時,它們在[LB,UB]區間內似乎不是均勻分布的。 確實確實從[LB,UB]采樣了整數,但僅從該范圍內的偶數整數采樣了。 例如,這是使用按位&方法從[20,50]采樣的5000個整數的直方圖: 使用按位&方法采樣的整數的直方圖

相比之下,這是使用mod運算符方法時類似的直方圖的樣子,當然可以正常工作: 在此處輸入圖片說明

我的按位和方法有什么問題? 有什么方法可以修改它,以便在定義的間隔內對偶數和奇數都進行采樣?

如果范圍差( UB-LB )為2 n -1,則效果很好,但如果例如2 n ,則根本無法正常工作。

按位&運算符查看其操作數的每對對應位,僅使用這兩個位執行an and ,然后將結果放入結果的對應位。

因此,如果UB-LB的最后一位為0,則結果的最后一位為0 也就是說,如果UB-LB為偶數,則每個輸出都將為偶數。

&不適用於此目的,除非UB-LB+1為2的冪。如果要查找模數,則沒有通用的捷徑:編譯器已經以已知的最快方式實現了%

請注意,我說的不是一般的快捷方式。 對於編譯時已知的UB-LB特定值,可以有更快的方法。 並且如果您能以某種方式安排UBLB具有編譯器在編譯時可以計算的值,則在編寫%時將使用它們。

順便說一句,使用%實際上不會在該范圍內產生均勻分布的整數,除非該范圍的大小是2的冪。否則,對於某些值,必須稍有偏差,因為int64()的范圍int64()函數不能在所需范圍內平均分配。 偏差可能太小而不能特別影響您的仿真,但是不好的隨機數生成器在過去破壞了隨機仿真,並將再次發生。

如果要在任意范圍內分配統一的隨機數,請使用C ++ 11中的std::uniform_int_distribution或Boost中的同名類。

僅當間隔大小為2的冪時,兩者才等效。 通常,y%x和y&(x-1)不相同。

例如,x%5產生從0到4的數字(對於負數x則為-4),但是x&4產生0或4,而不是1,2或3,因為按位運算符的工作方式...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM