Skip to content

Instantly share code, notes, and snippets.

@sh1ch
Last active March 27, 2020 01:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sh1ch/cb4e7fd56229433b7168f86701a2b4ac to your computer and use it in GitHub Desktop.
Save sh1ch/cb4e7fd56229433b7168f86701a2b4ac to your computer and use it in GitHub Desktop.
Xorshift の実装例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XorshiftRandom
{
/// <summary>
/// <see cref="Random"/> クラスは、Xorshift RNGs による疑似乱数ジェネレーターです。
/// <para>
/// 静的に乱数を運用するために使用します。通常、エフェクトなど再現性を考慮しない要素に利用します。
/// </para>
/// </summary>
public static class Random
{
#region Fields
private static RandomState _State = new RandomState();
#endregion
#region Public Methods
/// <summary>
/// 疑似乱数ジェネレーターの状態を決めるシード値を設定します。
/// </summary>
/// <param name="seed">擬似乱数系列の開始値を計算するために使用するシード値。</param>
public static void SetSeed(long seed)
{
_State.SetSeed((ulong)seed);
}
/// <summary>
/// 疑似乱数ジェネレーターの状態を決めるシード値を設定します。
/// </summary>
/// <param name="seed">擬似乱数系列の開始値を計算するために使用するシード値。</param>
public static void SetSeed(ulong seed)
{
_State.SetSeed(seed);
}
/// <summary>
/// 指定した範囲のランダムな数値を取得します。(指定した値を含む)
/// </summary>
/// <param name="minValue">最小値。</param>
/// <param name="maxValue">最大値。</param>
/// <returns>疑似乱数値。</returns>
public static int Range(int minValue, int maxValue)
{
return _State.Range(minValue, maxValue);
}
/// <summary>
/// 指定した範囲のランダムな数値を取得します。(指定した値を含む)
/// </summary>
/// <param name="minValue">最小値。</param>
/// <param name="maxValue">最大値。</param>
/// <returns>疑似乱数値。</returns>
public static double Range(double minValue = 0.0D, double maxValue = 1.0D)
{
return _State.Range(minValue, maxValue);
}
/// <summary>
/// 疑似乱数を取得します。
/// <para>
/// 乱数の範囲は、0 ≦ w ≦ (2^64) -1 です。(値を含む)
/// </para>
/// </summary>
/// <returns>疑似乱数値。</returns>
public static ulong GetNext()
{
return _State.GetNext();
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XorshiftRandom
{
/// <summary>
/// <see cref="RandomState"/> クラスは、Xorshift RNGs による疑似乱数ジェネレーターです。
/// <para>
/// 個別に乱数を運用するために使用します。通常、乱数の再現性を必要とするコンテンツに利用します。
/// </para>
/// </summary>
public class RandomState
{
#region Fields
private ulong _x = 123456789U;
private ulong _y = 362436069U;
private ulong _z = 521288629U;
private ulong _w = 88675123U;
private static ulong MIN_VALUE = ulong.MinValue;
private static ulong MAX_VALUE = ulong.MaxValue;
#endregion
#region Properties
#endregion
#region Initializes
/// <summary>
/// <see cref="RandomState"/> クラスの新しいインスタンスを初期化します。
/// </summary>
public RandomState() : this(88675123U) { }
/// <summary>
/// <see cref="RandomState"/> クラスの新しいインスタンスを初期化します。
/// </summary>
/// <param name="seed">擬似乱数系列の開始値を計算するために使用するシード値。</param>
public RandomState(int seed)
{
}
/// <summary>
/// <see cref="RandomState"/> クラスの新しいインスタンスを初期化します。
/// </summary>
/// <param name="seed">擬似乱数系列の開始値を計算するために使用するシード値。</param>
public RandomState(uint seed)
{
}
/// <summary>
/// <see cref="RandomState"/> クラスの新しいインスタンスを初期化します。
/// </summary>
/// <param name="seed">擬似乱数系列の開始値を計算するために使用するシード値。</param>
public RandomState(long seed)
{
}
/// <summary>
/// <see cref="RandomState"/> クラスの新しいインスタンスを初期化します。
/// </summary>
/// <param name="seed">擬似乱数系列の開始値を計算するために使用するシード値。</param>
public RandomState(ulong seed)
{
}
#endregion
#region Public Methods
/// <summary>
/// 疑似乱数ジェネレーターの状態を決めるシード値を設定します。
/// </summary>
/// <param name="seed">擬似乱数系列の開始値を計算するために使用するシード値。</param>
public void SetSeed(long seed)
{
SetSeed((ulong)seed);
}
/// <summary>
/// 疑似乱数ジェネレーターの状態を決めるシード値を設定します。
/// </summary>
/// <param name="seed">擬似乱数系列の開始値を計算するために使用するシード値。</param>
public void SetSeed(ulong seed)
{
_x = seed;
_y = _x * 3266489917U + 1;
_z = _y * 3266489917U + 1;
_w = _z * 3266489917U + 1;
}
/// <summary>
/// 指定した範囲のランダムな数値を取得します。(指定した値を含む)
/// </summary>
/// <param name="minValue">最小値。</param>
/// <param name="maxValue">最大値。</param>
/// <returns>疑似乱数値。</returns>
public int Range(int minValue, int maxValue)
{
return Convert.ToInt32(Range((double)minValue, (double)maxValue));
}
/// <summary>
/// 指定した範囲のランダムな数値を取得します。(指定した値を含む)
/// </summary>
/// <param name="minValue">最小値。</param>
/// <param name="maxValue">最大値。</param>
/// <returns>疑似乱数値。</returns>
public double Range(double minValue = 0.0D, double maxValue = 1.0D)
{
var w = ToNormalize(GetNext());
return minValue + (w * (maxValue - minValue));
}
/// <summary>
/// 疑似乱数を取得します。
/// <para>
/// 乱数の範囲は、0 ≦ w ≦ (2^64) -1 です。(値を含む)
/// </para>
/// </summary>
/// <returns>疑似乱数値。</returns>
public ulong GetNext()
{
ulong t = _x ^ (_x << 11);
// ulong が 64 bit まで
_x = _y;
_y = _z;
_z = _w;
_w = (_w ^ (_w >> 19)) ^ (t ^ (t >> 8));
return _w;
}
#endregion
#region Private Methods
private double ToNormalize(ulong w)
{
var max = MAX_VALUE;
var min = MIN_VALUE;
return ((double)(w - MIN_VALUE)) / ((double)(MAX_VALUE - MIN_VALUE));
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment