本日は
Go の練習がてらXorshiftを実装してみます.
実装例(struct を使う場合)
package main
import "fmt"
type xorshift32 struct {
seed uint32
}
func (r *xorshift32) rand() uint32 {
y := r.seed
y = y ^ (y << 13)
y = y ^ (y >> 17)
y = y ^ (y << 5)
r.seed = y
return y
}
func uniform(generator xorshift32) func() float32 {
inner := func() float32 {
return float32(generator.rand()) / float32(^uint32(0))
}
return inner
}
func calcPi() {
xor32 := xorshift32{seed: 2463534242}
u01 := uniform(xor32)
N := 100000000
counter := 0
for i := 0; i < N; i++ {
x := u01()
y := u01()
if x*x+y*y < 1.0 {
counter += 1
}
}
fmt.Println(4 * float64(counter) / float64(N))
}
func test1() {
xor32 := xorshift32{seed: 2463534242}
for i := 0; i < 10; i++ {
fmt.Println(xor32.rand())
}
}
func main() {
test1()
calcPi()
}
xor32.rand() を複数呼び出す際に seed
,y
の値を記録しておく必要があるので struct
を使いました.ポインターレシーバーのの良い練習になりました.
実装例(クロージャを用いた場合)
Xorshift の Python 実装
にならって書いた場合です.
package main
import "fmt"
func randXorshit32(seed uint32) func() uint32 {
var y uint32 = seed
inner := func() uint32 {
y = y ^ (y << 13)
y = y ^ (y >> 17)
y = y ^ (y << 5)
return y
}
return inner
}
func uniform(generator func() uint32) func() float32 {
inner := func() float32 {
return float32(generator()) / float32(^uint32(0))
}
return inner
}
func calcPi() {
xor32 := randXorshit32(2463534242)
u01 := uniform(xor32)
N := 100000000
counter := 0
for i := 0; i < N; i++ {
x := u01()
y := u01()
if x*x+y*y < 1.0 {
counter += 1
}
}
fmt.Println(4 * float64(counter) / float64(N))
}
func test1() {
xor32 := randXorshit32(2463534242)
for i := 0; i < 10; i++ {
fmt.Println(xor32())
}
}
func main() {
test1()
calcPi()
}
書いていて思ったこと
Pythonに慣れてしまった人間から見るとGoがデフォルト引数をサポートしていないというのがとても不便に感じてしまします.
- Default value in Go's method
- Does function or method support argument default value?
- Default Value in structs?
そういうもんなんだろうな・・・.