隨機數(三)
測試程式
在 圖靈社群:隨機數(二)中,我們給出了一個 NrRandom 類,能夠產生更好的偽隨機序列。那麼,它與 .NET Framework 中的 Random 類相比,效能如何呢?讓我們寫一個測試程式吧:
using System;
using System.Diagnostics;
namespace Skyiv.Tester
{
static class NrRandomTester
{
static readonly Stopwatch timer = new Stopwatch();
static void TestNext1(Random rand, int n)
{
long sum = 0;
timer.Restart();
for (var i = 0; i < n; i++) sum += rand.Next();
timer.Stop();
Console.WriteLine("{0,14} {1,6:F3} {2:N0}", rand.GetType(),
timer.Elapsed.TotalSeconds, (double)sum/n);
}
static void TestNext2(Random rand, int n, int max)
{
long sum = 0;
timer.Restart();
for (var i = 0; i < n; i++) sum += rand.Next(max);
timer.Stop();
Console.WriteLine("{0,14} {1,6:F3} {2:N6}", rand.GetType(),
timer.Elapsed.TotalSeconds, (double)sum/n);
}
static void TestNext3(Random rand, int n, int min, int max)
{
long sum = 0;
timer.Restart();
for (var i = 0; i < n; i++) sum += rand.Next(min, max);
timer.Stop();
Console.WriteLine("{0,14} {1,6:F3} {2,12:N3}", rand.GetType(),
timer.Elapsed.TotalSeconds, (double)sum/n);
}
static void TestNextDouble(Random rand, int n)
{
double sum = 0;
timer.Restart();
for (var i = 0; i < n; i++) sum += rand.NextDouble();
timer.Stop();
Console.WriteLine("{0,14} {1,6:F3} {2:N10}", rand.GetType(),
timer.Elapsed.TotalSeconds, sum/n);
}
static void TestNextBytes(Random rand, int n, int size)
{
long sum = 0;
var bs = new byte[size];
timer.Restart();
for (var i = 0; i < n; i++) {
rand.NextBytes(bs);
foreach (var v in bs) sum += v;
}
timer.Stop();
Console.WriteLine("{0,14} {1,6:F3} {2:N6}", rand.GetType(),
timer.Elapsed.TotalSeconds, (double)sum/n/size);
}
static void Main()
{
Console.WriteLine("{0} {1}-bit", Environment.OSVersion,
Environment.Is64BitOperatingSystem ? 64 : 32);
Console.WriteLine("CLR {0}", Environment.Version);
var r0 = new Random();
var nr = new NrRandom();
Console.WriteLine(); int n = 1000000000, max = int.MaxValue;
Console.WriteLine("Next(): {0,27:N0}", (max-1)/2.0);
TestNext1(r0, n); TestNext1(nr, n);
Console.WriteLine(); max = 10000;
Console.WriteLine("Next(max): {0,23:N6}", (max-1)/2.0);
TestNext2(r0, n, max); TestNext2(nr, n, max);
Console.WriteLine(); max = int.MaxValue; int min = 1 - max;
Console.WriteLine("Next(min,max): {0,19:N3}", (max-1L+min)/2.0);
TestNext3(r0, n, min, max); TestNext3(nr, n, min, max);
Console.WriteLine();
Console.WriteLine("NextDouble(): {0,20:N10}", 1/2.0);
TestNextDouble(r0, n); TestNextDouble(nr, n);
Console.WriteLine(); int size = 1000000, m = n / size;
Console.WriteLine("NextBytes(buffer): {0,13:N6}", byte.MaxValue/2.0);
TestNextBytes(r0, m, size); TestNextBytes(nr, m, size);
}
}
}
編譯和執行
Linux 64-bit 作業系統
在 Arch Linux 64-bit 作業系統中編譯和執行:
$ mcs NrRandomTester.cs NrRandom.cs $ mono NrRandomTester.exe Unix 4.6.3.1 64-bit CLR 4.0.30319.42000 Next(): 1,073,741,823 System.Random 14.920 1,073,744,468 Skyiv.NrRandom 16.619 1,073,777,257 Next(max): 4,999.500000 System.Random 19.831 4,999.476177 Skyiv.NrRandom 15.244 4,999.590640 Next(min,max): 0.000 System.Random 41.936 8,672.938 Skyiv.NrRandom 16.405 -13,744.444 NextDouble(): 0.5000000000 System.Random 17.517 0.4999909586 Skyiv.NrRandom 14.077 0.5000026850 NextBytes(buffer): 127.500000 System.Random 15.483 127.498822 Skyiv.NrRandom 6.291 127.503321
輸出結果中:
方法名稱: 期望的平均值 System.Random 執行時間(秒) 實際的平均值 Skyiv.NrRandom 執行時間(秒) 實際的平均值
其中每種方法都生成 109 個隨機數來進行測試。可以看出:
- 對於 Next() 方法,NrRandom 類的效能略差於 Random 類。
- 對於 Next(max) 方法,NrRandom 類的效能優於 Random 類。
- 對於 Next(min,max) 方法,NrRandom 類的效能大大優於 Random 類。
- 對於 NextDouble() 方法,NrRandom 類的效能優於 Random 類。
- 對於 NextBytes(buffer) 方法,NrRandom 類的效能大大優於 Random 類。
- 對於這兩個類,各個方法生成的隨機數的平均值都中規中矩。
Windows 64-bit 作業系統
C> NrRandomTester.exe Microsoft Windows NT 6.1.7601 Service Pack 1 64-bit CLR 4.0.30319.42000 Next(): 1,073,741,823 System.Random 11.030 1,073,763,381 Skyiv.NrRandom 11.944 1,073,745,494 Next(max): 4,999.500000 System.Random 16.585 4,999.546877 Skyiv.NrRandom 10.319 4,999.411534 Next(min,max): 0.000 System.Random 31.271 37,382.863 Skyiv.NrRandom 11.942 -39,145.860 NextDouble(): 0.5000000000 System.Random 13.122 0.5000071087 Skyiv.NrRandom 9.548 0.4999977242 NextBytes(buffer): 127.500000 System.Random 12.009 127.497139 Skyiv.NrRandom 7.090 127.503601
測試結果與 Linux 64-bit 作業系統一致。
Windows 32-bit 作業系統
C:> NrRandomTester.exe Microsoft Windows NT 6.1.7601 Service Pack 1 32-bit CLR 4.0.30319.42000 Next(): 1,073,741,823 System.Random 11.455 1,073,751,534 Skyiv.NrRandom 35.625 1,073,754,659 Next(max): 4,999.500000 System.Random 18.431 4,999.490003 Skyiv.NrRandom 33.778 4,999.364559 Next(min,max): 0.000 System.Random 50.525 17,712.270 Skyiv.NrRandom 46.544 -10,609.773 NextDouble(): 0.5000000000 System.Random 14.538 0.4999985216 Skyiv.NrRandom 26.370 0.4999974172 NextBytes(buffer): 127.500000 System.Random 11.726 127.500430 Skyiv.NrRandom 9.558 127.500100
測試結果出乎意料,除了 Next(min,max) 和 NextBytes(buffer) 方法,NrRandom 類的效能略優於 Random 類,其餘方法,NrRandom 類的效能均大大差於 Random 類。我想,這是由於 NrRandom 類生成隨機數時,使用 long(64-bit 整數)進行運算,而 32-bit 的作業系統的 64-bit 整數運算的效能低下造成的。
相關文章
- 隨機數隨機
- python生成隨機數、隨機字串Python隨機字串
- [隨機數詳解]生成一個隨機數,生成指定範圍的隨機數及隨機陣列去重隨機陣列
- 隨機數(一)隨機
- 隨機數(二)隨機
- 生成隨機數隨機
- groovy : 隨機數隨機
- 隨機範圍小數和隨機範圍整數隨機
- [Z]Oracle 的隨機數、隨機日期和時間、隨機字串Oracle隨機字串
- 數學一|概統|三、多維隨機變數及其分佈隨機變數
- JavaScript 生成隨機數JavaScript隨機
- C++ 隨機數C++隨機
- 明明的隨機數隨機
- 隨機數擴充隨機
- mysql生成隨機數MySql隨機
- 隨機數漫談隨機
- Js Math隨機數JS隨機
- Linux Shell 生成隨機數和隨機字串Linux隨機字串
- Python隨機數與隨機字串詳解Python隨機字串
- Matlab 隨機生成兩個數值之間的隨機數Matlab隨機
- matlab產生隨機數或隨機矩陣Matlab隨機矩陣
- 偽隨機數是什麼?偽隨機數生成方法有哪些?隨機
- 從oracle表中隨機取記錄,產生隨機數和隨機字串Oracle隨機字串
- 隨機數生成器隨機
- java隨機數生成原理Java隨機
- Java 隨機數探祕Java隨機
- R產生隨機數隨機
- PHP獲取隨機數PHP隨機
- javascript 隨機數區間JavaScript隨機
- Random獲取隨機數random隨機
- 生成隨機整數方法隨機
- python 隨機數生成Python隨機
- ORACLE裡的隨機數Oracle隨機
- C++生成隨機數C++隨機
- Python如何隨機生成1到100的隨機數?Python隨機
- 熵不起得隨機數熵隨機
- 聊一聊隨機數安全隨機
- 微信小程式生成隨機數微信小程式隨機