LoginSignup
1
1

More than 5 years have passed since last update.

XorShiftの実装 軽量版

Last updated at Posted at 2018-10-13

以前作った記事が余計な処理含みすぎて複雑になりすぎたので(若干言語のラインナップは変わってますが)シェイプアップして書き直しました。
対応言語は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]
}

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1