隨機數(二)
均勻分佈
Numerical Recipes, The Art of Scientific Computing, Third Edition, Chapter 7 Random Numbers:
Ran 程式
typedef unsigned int Uint; // 32-bit unsinged integer
typedef unsigned long long int Ullong; // 64-bit unsinged integer
typedef double Doub; // 64-bit floating point
注意,由於 Ullong 和 Doub 都是 64-bit 的,所以把 Ullong 轉換為 Doub 時有可能喪失精度。即,上述程式中的 int64() 的不同的值有可能對應 doub() 的相同的值。
1.0 / (1.0 + ULLONG_MAX) == 1.0 / ULLONG_MAX == 5.42101086242752E-20
0.0 <= doub() <= 1.0 // 注意: doub() 有可能等於 1.0
NrRandom 類
使用上述 Ran 程式中的演算法,可以得到以下 C# 程式:
namespace Skyiv {
using System;
public sealed class NrRandom : Random
{
ulong v1, v8, v16, v32, u, v = 4101842887655102017, w = 1;
int c1 = 0, c8 = 0, c16 = 0, c32 = 0;
protected override double Sample() {
return 1 / (1.0 + uint.MaxValue) * NextUInt32(); }
public override double NextDouble() { return Sample(); }
public override int Next() { return Next(int.MaxValue); }
public NrRandom() : this((ulong)DateTime.Now.Ticks) { }
public NrRandom(ulong seed)
{
u = v ^ seed; NextUInt64();
v = u; NextUInt64();
w = v; NextUInt64();
}
public ulong NextUInt64()
{
u = u * 2862933555777941757 + 7046029254386353087;
v ^= v >> 17; v ^= v << 31; v ^= v >> 8;
w = 4294957665U * (w & 0xffffffff) + (w >> 32);
ulong x = u ^ (u << 21); x ^= x >> 35; x ^= x << 4;
return (x + v) ^ w;
}
public override int Next(int max)
{
if (max < 0) throw new ArgumentOutOfRangeException(nameof(max));
return (int)(Sample() * max);
}
public override int Next(int min, int max)
{
if (min > max) throw new ArgumentOutOfRangeException(nameof(min));
return (int)(min + (long)(Sample() * (max - (long)min)));
}
public override void NextBytes(byte [] buffer)
{
if (buffer == null) throw new ArgumentNullException(nameof(buffer));
for (int i = 0; i < buffer.Length; i++) buffer[i] = NextByte();
}
public uint NextUInt32()
{
if (c32-- != 0) return (uint)(v32 >>= 32);
c32 = 1; return (uint)(v32 = NextUInt64());
}
public ushort NextUInt16()
{
if (c16-- != 0) return (ushort)(v16 >>= 16);
c16 = 3; return (ushort)(v16 = NextUInt64());
}
public byte NextByte()
{
if (c8-- != 0) return (byte)(v8 >>= 8);
c8 = 7; return (byte)(v8 = NextUInt64());
}
public bool NextBoolean()
{
if (c1-- != 0) return ((v1 >>= 1) & 1) != 0;
c1 = 63; return ((v1 = NextUInt64()) & 1) != 0;
}
}
}
簡要說明:
- NrRandom(ulong seed) 對應 Ran(Ullong j)。
- ulong NextUInt64() 對應 Ullong int64()。
- 上述兩個方法是本演算法的核心部分,其他方法都基於這兩者。
- double NextDouble() 要求在 [0.0, 1.0) 內,所以和 Doub doub() 有所不同。
我想,在需要高質量的偽隨機數生成器的場合,這個 NrRandom 類可以替代 .NET Framework 中的 Random 類。而且,它還有以下的方法:
- ulong NextUInt64()
- uint NextUInt32()
- ushort NextUInt16()
- byte NextByte()
- bool NextBoolean()
參考資料
相關文章
- BZOJ4282 : 慎二的隨機數列隨機
- 隨機數隨機
- 數學一|概統|二、隨機變數及其分佈隨機變數
- 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隨機
- 熵不起得隨機數熵隨機