XorShift On C#

CSharp · Console

/Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using XorShifts;

//XorShift Module
//using System;
//using System.Collections.Generic;

namespace XorShifts{
	class XorShift{
		private IEnumerator<uint> r;
		public static readonly Dictionary<string,uint> defaults=new Dictionary<string,uint>(){
			{"x",123456789},
			{"y",362436069},
			{"z",521288629},
			{"w",88675123}
		};
		public readonly Dictionary<string,uint> seeds;
		public uint randCount=0;

		public XorShift(uint? _w=null,uint? _x=null,uint? _y=null,uint? _z=null){
			uint w=_w ?? (uint)Environment.TickCount;
			uint x=_x ?? w<<13;
			uint y=_y ?? (w>>9)^(x<<6);
			uint z=_z ?? y>>7;
			seeds=new Dictionary<string,uint>(){
				{"x",x},{"y",y},{"z",z},{"w",w}
			};
			r=randGen(w,x,y,z);
		}

		public IEnumerator<uint> randGen(uint w,uint x,uint y,uint z){
			uint t;
			for(;;){
				t=x^(x<<11);
				x=y;
				y=z;
				z=w;
				yield return w=(w^(w>>19))^(t^(t>>8));
			}
		}

		public uint rand(){
			randCount++;
			r.MoveNext();
			return r.Current;
		}

		public int randInt(int min=0,int max=0x7FFFFFFF){
			return (int)(rand()%(max-min+1))+min;
		}

		public float randFloat(float min=0,float max=1){
			return (float)(rand()%0xFFFF)/0xFFFF*(max-min)+min;
		}

		public T[] shuffle<T>(T[] _arr){
			var arr=(T[])_arr.Clone();
			for(int i=0;i<=arr.Length-2;i++){
				int r=randInt(i,arr.Length-1);
				T tmp=arr[i];
				arr[i]=arr[r];
				arr[r]=tmp;
			}
			return arr;
		}

		public List<T> shuffle<T>(List<T> _arr){
			var arr=new List<T>(_arr);
			for(int i=0;i<=arr.Count-2;i++){
				int r=randInt(i,arr.Count-1);
				T tmp=arr[i];
				arr[i]=arr[r];
				arr[r]=tmp;
			}
			return arr;
		}

		public class defaultSeed:XorShift{
			public defaultSeed():base(
				defaults["w"],
				defaults["x"],
				defaults["y"],
				defaults["z"]
			){}
		}
	}
}
//XorShift End

namespace TestXS{
	public class TestXS{
		public static void Main(){
			//XorShift乱数ジェネレータの初期化
			// 論文デフォルトシード
			var r_def=new XorShift.defaultSeed();
			// 固定値シード
			var r_const=new XorShift(100);
			// 時間シード
			var r=new XorShift();
	
			//デフォルトシード値の取得
			Console.WriteLine(">> defaults");
			foreach(var i in XorShift.defaults.Keys){
				Console.WriteLine("{0}:{1}",i,XorShift.defaults[i]);
			}
	
			//適用したシード値の取得
			Console.WriteLine(">> seeds in r");
			foreach(var i in r.seeds.Keys){
				Console.WriteLine("{0}:{1}",i,XorShift.defaults[i]);
			}
	
			//乱数の生データを取得
			Console.WriteLine(">> rand 0 to UInt32Max");
			for(int i=0;i<5;i++){
				Console.WriteLine(r_def.rand());
			}
	
			//0-100の乱数(100含む)を整数で取得
			Console.WriteLine(">> randInt 0 to 100");
			for(int i=0;i<5;i++){
				Console.WriteLine(r_const.randInt(0,100));
			}
	
			//0-1の乱数を浮遊小数点で取得
			Console.WriteLine(">> randFloat 0 to 1");
			for(int i=0;i<5;i++){
				Console.WriteLine(r.randFloat());
			}
	
			//静的配列のシャッフル
			//値渡しとなるので元の配列は破壊されない
			Console.WriteLine(">> shuffle Array");
			int[] a=Enumerable.Range(0,20).ToArray();
			Console.WriteLine(String.Join(", ",r.shuffle(a)));
			Console.WriteLine(String.Join(", ",a));
	
			//List<T>のシャッフル
			Console.WriteLine(">> shuffle List<T>");
			var b=new List<int>(Enumerable.Range(0,20));
			Console.WriteLine(String.Join(", ",r.shuffle(b)));
			Console.WriteLine(String.Join(", ",b));
	
			//今の乱数を回した回数
			Console.WriteLine(">> randCount in r");
			Console.WriteLine(r.randCount);
		}
	}
}
;