2016-08-18 19 views
2

我正在開發一個受到嚴格監管審查的遊戲平臺。我選擇Math.NET是因爲它看起來很合適。不過,我剛收到審計員的回覆。Math.NET CryptoRandomSource接下來是偏向的

評論請如果這是準確的,它是如何解決?


在RandomSource(),接着(INT,INT)被定義如下:

public override sealed int Next(int minValue, int maxValue) 
    { 
     if (minValue > maxValue) 
     { 
      throw new ArgumentException(Resources.ArgumentMinValueGreaterThanMaxValue); 
     } 

     if (_threadSafe) 
     { 
      lock (_lock) 
      { 
       return (int)(DoSample()*(maxValue - minValue)) + minValue; 
      } 
     } 

     return (int)(DoSample()*(maxValue - minValue)) + minValue; 
    } 

這如之前創建相同的方式偏置。使用來自RNG的未縮放的值,並將其乘以該範圍而不預先消除偏差(除非該範圍是2的冪,則將存在偏差)。

+0

什麼是'DoSample()'?如果不知道返回正是它很難找出這裏發生了什麼。這是否只是一種uniformaly分佈的隨機0和1之間的數字(以及它包含/排除哪個終點)?您是否知道這實際上沒有偏見? – Chris

+0

該方法的預期回報值是多少?它應該能夠返回maxValue或minValue嗎?此外,你還需要做一些基本測試,比如調用Next(0,1)'數百萬次(或數十億次),並計算結果,看看它們是否有顯着不同(當它們靠近時,有時候它們很難算出來,如果它們對於大樣本量是不同的數量級,那麼你可以肯定地發現有什麼錯誤,尤其是如果結果是可重複的。 – Chris

+0

DoSample()方法將返回一個介於0和1之間的double值。這個代碼沒有問題。我所引用的是審計人員遇到的問題,因爲當範圍不是2的冪時,不幸的是我們所有的範圍都是0-99,0-999,0-9999,0-99999。 – IntoNET

回答

2

更新:在此討論之後,Math.NET Numerics v3.13中的Next(minInclusive, maxExclusive)的實現已更改。自v3.13以來,它不再涉及浮點數,而是根據需要採樣具有所需位數的整數,以支持所請求的範圍(兩個冪),並拒絕實際範圍之外的那些位。這樣它避免了添加的字節採樣本身的頂部上的任何偏差(如例如由加密RNG提供)

假設:DoSample()返回值的範圍[0,1)均勻分佈的樣本(雙精度浮點數)。

將其乘以範圍R = max-min將導致在範圍[0,R)範圍內的均勻分佈樣本。將其轉換爲基本上爲地板的整數將會產生一個0,1,2,...,R-1之一的均勻分佈的離散樣本。我沒有看到R是偶數,奇數還是2的冪的事實可能會影響這一步中的偏見。

幾運行計算100'000'000樣品也並不表明明顯的偏見,但當然,這並不能證明:

var r = new CryptoRandomSource(); 
long[] h = new long[8]; 
for (int i = 0; i < 100000000; i++) 
{ 
    h[r.Next(2,7)]++; 
} 

0 
0 
19996313 
20001286 
19998092 
19998328 
20005981 
0 

0 
0 
20000288 
20002035 
20006269 
19994927 
19996481 
0 

0 
0 
19998296 
19997777 
20001463 
20002759 
19999705 
0 
+3

R是奇數,偶數還是其他什麼的原因是一種鴿子論爭。在[0,1)上返回的double將有2^52個可能的不同值(尾數是52位)。如果乘以R = 5,那麼你仍然有2^52個不同的值,但現在擴展到[0,5)。你發言,你有2^52的值,現在在{0,1,2,3,4}集合中。那麼這些2^52值中有多少映射到每個數字?顯然2^52不能被5整除,所以不能有相同的機會獲得該範圍內的每個整數。 – Chris

+2

爲了更好地理解缺陷在哪裏看一個只有三個相關位的小得多的浮點數。 DoSample現在返回0,1/8,2/8,3/8,4/8,5/8,6/8,7/8(八個值)。如果我們將它們乘以五,我們得到0,5/8,10/8,15/8,20/8,25/8,30/8,35/8。當地板上這給0,0,1,1,2,3,3,4 - 不統一! – Chris

+0

鑑於我的範圍總是已知的,例如0-99,如果我要生成一個0-100之間的數字,然後拋棄並重新生成,如果返回100,這不會解決2偏差問題的力量? – IntoNET

0

我想出了這個解決方案之間的0值和最大包容性。我不是數學專家,所以歡迎評論。

這似乎滿足監管規範我有說

2B)如果選擇了特定的隨機數是重新定標值的相等分佈的範圍之外,則允許丟棄的隨機數,並選擇序列中的下一重新防垢的目的「。

private readonly CryptoRandomSource _random = new CryptoRandomSource(); 

    private int GetRandomNumber(int max) 
    { 
     int number; 
     var nextPowerOfTwo = (int)Math.Pow(2, Math.Ceiling(Math.Log(max)/Math.Log(2))); 

     do 
     { 
      // Note: 2nd param of Next is an *exclusive* value. Add 1 to satisfy this 
      number = _random.Next(0, nextPowerOfTwo + 1); 
     } while (number > max); 

     return number; 
    }