以前作った記事が余計な処理含みすぎて複雑になりすぎたので(若干言語のラインナップは変わってますが)シェイプアップして書き直しました。
対応言語はJavaScript、VB、HSP、CommonLisp、C#、Python3、D言語、C++、Lua、Ruby、Tclです。
どの言語でも実装を合わせれば乱数の再現が可能です。
シードは変えた記録も載せていますが、時間をシードとして使い、偏り防止のためにこちらに倣って最初に40回ほど空転させています。
w=default
3701687786
458299110
2500872618
3633119408
516391518
2377269574
2599949379
717229868
137866584
395339113
w=time
2976958265
1697336156
4079413984
3258662528
4114964721
3389760686
247342821
359323276
3421929016
1548721468
実装
JavaScript(Node.js)
"use strict";
function* XorShift(w=88675123,x=123456789,y=362436069,z=521288629){
var t;
for(;;){
t=x^(x<<11);
x=y;y=z;z=w;
yield w=((w^(w>>>19))^(t^(t>>>8)))>>>0;
}
}
console.log("w=default");
const r=XorShift();
for(var i=0;i<10;i++){
console.log(r.next().value);
}
console.log("\nw=time");
const rt=XorShift(0|Date.now());
for(var i=0;i<40;i++) rt.next();
for(var i=0;i<10;i++){
console.log(rt.next().value);
}
VisualBasic(VB.Net)
Option Strict On
Imports System.Collections.Generic
Module Program
Iterator Function XorShift(Optional w As UInteger=88675123,Optional x As UInteger=123456789,Optional y As UInteger=362436069,Optional z As UInteger=521288629) As IEnumerator(Of UInteger)
Dim t As UInteger
Do
t=x Xor (x<<11)
x=y:y=z:z=w
w=(w Xor (w>>19)) Xor (t Xor (t>>8))
Yield w
Loop
End Function
Sub Main()
Console.WriteLine("w=default")
Dim r=XorShift()
For i=1 To 10
r.MoveNext()
Console.WriteLine(r.Current)
Next
Console.WriteLine($"{vbLf}w=time")
Dim rt=XorShift(CUInt(DateTime.UtcNow.Ticks And &H7FFFFFFF))
For i=1 To 40: rt.MoveNext(): Next
For i=1 To 10
rt.MoveNext()
Console.WriteLine(rt.Current)
Next
End Sub
End Module
HotSoupProcessor(HSP3)
# runtime "hsp3cl"
# cmpopt varinit 1
# module @XorShift co,w,x,y,z
#define global XorShift(%1,%2=88675123,%3=123456789,%4=362436069,%5=521288629) \
dimtype %1,5:newmod %1,@XorShift,%2,%3,%4,%5
#modinit int _w,int _x,int _y,int _z
w=_w:x=_x:y=_y:z=_z
newlab co,1:return
*xsLoop
t=x^(x<<11)
x=y:y=z:z=w
w=(w^(w>>19&$1FFF))^(t^(t>>8&$FFFFFF))
newlab co,1:return
goto*xsLoop
return
#modfunc xsMoveNext
gosub co: return double(strf("%u",w))
#modcfunc xsNext
gosub co: return double(strf("%u",w))
# global
mes "w=default"
XorShift r
repeat 10
mes strf("%.0f",xsNext(r))
loop
mes "\nw=time"
XorShift rt,1000*(60*(60*(24*gettime(3)+gettime(4))+gettime(5))+gettime(6))+gettime(7)
repeat 40: xsMoveNext rt: loop
repeat 10
mes strf("%.0f",xsNext(rt))
loop
CommonLisp
(defun XorShift(&key (w 88675123) (x 123456789) (y 362436069) (z 521288629))
(let (tt)
(lambda()
(setf tt (logxor x (logand (ash x 11) #xFFFFFFFF)))
(setf x y)(setf y z)(setf z w)
(setf w (logxor (logxor w (ash w -19)) (logxor tt (ash tt -8))))
)
)
)
(format t "w=default~%")
(let ((r (XorShift)))
(dotimes(i 10)
(format t "~d~%" (funcall r))
)
)
(format t "~%w=time~%")
(let ((rt (XorShift :w (get-universal-time))))
(dotimes(i 40) (funcall rt))
(dotimes(i 10)
(format t "~d~%" (funcall rt))
)
)
(quit)
C#
using System;
using System.Collections.Generic;
class Program{
static IEnumerator<uint> XorShift(uint w=88675123,uint x=123456789,uint y=362436069,uint z=521288629){
uint t;
for(;;){
t=x^(x<<11);
x=y;y=z;z=w;
yield return w=(w^(w>>19))^(t^(t>>8));
}
}
static void Main(){
Console.WriteLine("w=default");
var r=XorShift();
for(int i=0;i<10;i++){
r.MoveNext();
Console.WriteLine(r.Current);
}
Console.WriteLine("\nw=time");
var rt=XorShift((uint)DateTime.UtcNow.Ticks);
for(int i=0;i<40;i++) rt.MoveNext();
for(int i=0;i<10;i++){
rt.MoveNext();
Console.WriteLine(rt.Current);
}
}
}
Python3
from time import time
def XorShift(x=123456789,y=362436069,z=521288629,w=88675123):
while True:
t=x^(x<<11&0xFFFFFFFF)
x,y,z=y,z,w
w=(w^(w>>19))^(t^(t>>8))
yield w
print("w=default")
r=XorShift()
for i in range(0,10):
print(next(r))
print("\nw=time")
rt=XorShift(int(time()))
for i in range(0,40): next(rt)
for i in range(0,10):
print(next(rt))
Dlang(D言語)
import std.stdio;
import std.concurrency;
import std.datetime;
Generator!uint XorShift(uint w=88675123,uint x=123456789,uint y=362436069,uint z=521288629){
return new Generator!uint((){
yield(w);
uint t;
for(;;){
t=x^(x<<11);
x=y;y=z;z=w;
yield(w=(w^(w>>19))^(t^(t>>8)));
}
});
}
void main(){
writeln("w=default");
auto r=XorShift();
for(int i=0;i<10;i++){
r.popFront();
writeln(r.front);
}
writeln("\nw=time");
auto rt=XorShift(cast(uint)Clock.currTime().stdTime);
for(int i=0;i<40;i++) rt.popFront();
for(int i=0;i<10;i++){
rt.popFront();
writeln(rt.front);
}
}
C++
# include <iostream>
# include <stdint.h>
# include <time.h>
class XorShift{
private:
uint32_t w,x,y,z,t;
public:
XorShift(uint32_t w=88675123,uint32_t x=123456789,uint32_t y=362436069,uint32_t z=521288629){
this->w=w;this->x=x;this->y=y;this->z=z;
}
uint32_t next(){
t=x^(x<<11);
x=y;y=z;z=w;
return w=(w^(w>>19))^(t^(t>>8));
}
};
int main(){
using namespace std;
cout<<"w=default"<<endl;
XorShift r;
for(auto i=0;i<10;i++){
cout<<r.next()<<endl;
}
cout<<"\nw=time"<<endl;
XorShift rt(time(nullptr));
for(auto i=0;i<40;i++) rt.next();
for(auto i=0;i<10;i++){
cout<<rt.next()<<endl;
}
return 0;
}
Lua
function XorShift(w,x,y,z)
w=w or 88675123:x=x or 123456789:y=y or 362436069:z=z or 521288629
return coroutine.create(function()
while true do
t=x~(x<<11&0xFFFFFFFF)
x,y,z=y,z,w
w=(w~(w>>19))~(t~(t>>8))
coroutine.yield(w)
end
end)
end
print("w=default")
local r=XorShift()
for i=1,10 do
print(({coroutine.resume(r)})[2])
end
print("\nw=time")
local rt=XorShift(os.time())
for i=1,40 do coroutine.resume(rt) end
for i=1,10 do
print(({coroutine.resume(rt)})[2])
end
Ruby
def XorShift(x=123456789,y=362436069,z=521288629,w=88675123)
Fiber.new do
while true do
t=x^(x<<11&0xFFFFFFFF)
x,y,z=y,z,w
w=(w^(w>>19))^(t^(t>>8))
Fiber.yield(w)
end
end
end
puts "w=default"
r=XorShift()
(1..10).each do
puts r.resume
end
puts "\nw=time"
rt=XorShift(Time.now.tv_sec)
(1..40).each do rt.resume end
(1..10).each do
puts rt.resume
end
Tcl
proc XorShift {{w 88675123} {x 123456789} {y 362436069} {z 521288629}} {
yield [info coroutine]
while true {
set t [expr $x^($x<<11&0xFFFFFFFF)]
set x $y;set y $z;set z $w
yield [set w [expr ($w^($w>>19))^($t^($t>>8))]]
}
}
puts "w=default"
coroutine r XorShift
for {set i 0} {$i<10} {incr i} {
puts [r]
}
puts "\nw=time"
coroutine rt XorShift [expr [clock clicks -milliseconds]&0xFFFFFFFF]
for {set i 0} {$i<40} {incr i} rt
for {set i 0} {$i<10} {incr i} {
puts [rt]
}