[英]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
特定值,可以有更快的方法。 並且如果您能以某種方式安排UB
和LB
具有編譯器在編譯時可以計算的值,則在編寫%
時將使用它們。
順便說一句,使用%
實際上不會在該范圍內產生均勻分布的整數,除非該范圍的大小是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.