問題:
在計算旅行商問題中的歐幾里得距離時,我試圖使用 3-opt 演算法來交換某些節點;因為大多情況下我有大約超過500個節點,我需要隨機地選擇至少1/3的節點進行交換。
所以我需要一個快速產生隨機數的函式(標準函式rand()太慢了)。不需要多麼巧妙,差不多就行了。
注:忘了說,我無法使用除了標準庫(比如 STL,iostream 等)以外的庫,所以 boost 庫也不行。
AndyV 的最佳答案:
其他人的答案提到了 Marsaglia 的 Xorshift 演算法(https://en.wikipedia.org/wiki/Xorshift),但是沒人貼程式碼。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
static unsigned long x=123456789, y=362436069, z=521288629; unsigned long xorshf96(void) { //period 2^96-1 unsigned long t; x ^= x << 16; x ^= x >> 5; x ^= x << 1; t = x; x = y; y = z; z = t ^ x ^ y; return z; } |
這段程式碼幾乎在任何地方都適用;然而當我試圖產生隨機的二進位制矩陣時,它卻失敗了。大概是 95×95 的矩陣,它生成了太多或太少的奇異矩陣(我忘了具體是多還是少了)。這個隨機數生成器相當於一個線性反饋移位暫存器。不過如果你要做加密或者蒙特卡洛的相關工作,這個生成器就不能用了。
補充:Xorshift 演算法介紹
Xorshift 隨機數生成器是 George Marsaglia 發明的一類偽隨機數生成器。它們通過和自己邏輯移位後的數進行異或操作來生成序列中的下一個數。這在現代計算機體系結構非常快。它們是線性反饋移位暫存器的一個子類,其簡單的實現使它們速度更快且使用更少的空間。然而,必須仔細選擇合適引數以達到長週期。
Xorshift生成器是非密碼安全的隨機數生成器中最快的一種,只需要非常短的程式碼和狀態。雖然它們沒有進一步改進以通過統計檢驗,這個缺點非常著名且容易修改(Marsaglia 在原來的論文中指出),用複合一個非線性函式的方式,可以得到比如像 xorshift+ 或 xorshift* 生成器。一個簡單的C語言實現的 xorshift+ 生成器通過了所有的 BigCrush 的測試(比 Mersenne Twister 演算法和 WELL 演算法的失敗次數減少了一個數量級),而且在 x86 上產生一個隨機數通常只需要不到十個時鐘週期,多虧了指令流水線。
因為一般的 xorshift 生成器(沒有非線性這一步)在一些統計測試中失敗了,所以經常被指責是不可靠的。
示例實現
一個 xorshift 生成器的 C/C++ 版本實現:
1 2 3 4 5 6 7 8 9 10 |
#include <stdint.h> /* These state variables must be initialized so that they are not all zero. */ uint32_t x, y, z, w; uint32_t xorshift128(void) { uint32_t t = x ^ (x << 11); x = y; y = z; z = w; return w = w ^ (w >> 19) ^ t ^ (t >> 8); } |
這個演算法有一個最大的週期2128 − 1 ,且通過了 diehard 測試。不過,它在 TestU01 框架的 BigCrush 測試套件中的 MatrixRank 和 LinearComp 測試中失敗了。