【Python】擬似乱数は本当にランダムな値を生成するのか

Pythonには擬似乱数生成のためのRandomクラスが標準で用意されていますが,
これが本当にランダムな値を生成しているのかを,Pythonの勉強も兼ねて調べてみました.

本稿は以下の記事をみて「へぇ〜意外と乱数って法則性有るんだなあ」と思って,
方法をそのまま真似たものです.

Unityの乱数が本当にランダムかどうか見てみた | ワンダープラネットエンジニア Blog

乱数の画像化

(256, 256)の画像にrandom.randintで生成される整数値のタプルをポチポチ2万点打っていきます.
画像処理のライブラリはpillowを使いました.(導入が面倒だった...

import random
from PIL import Image
from PIL import ImageDraw

def drawing(img):
	for i in range(0, 20000):
		x = random.randint(0, 255)
		y = random.randint(0, 255)
		draw = ImageDraw.Draw(img)
		draw.point((x, y), 0)

	return img

def make_image(screen, bgcolor, filename):
	img = Image.new('1', screen, bgcolor)
	img = drawing(img)
	img.show()
	img.save(filename)

if __name__ == '__main__':
	screen = (256, 256)
	bgcolor = 'white'
	filename = 'image_dot_pattern.jpg'

	make_image(screen, bgcolor, filename)
	
生成される画像

f:id:yusuke_ujitoko:20150209131230j:plain

規則性はなさそうに見えます.ランダムかな?
(見える人にはなにか見える??)

乱数の画像化その2!

さてと,引用した記事の中と同じように,先ほどとは違う方法で画像を作ります!
具体的には,256×256 の中のそれぞれのピクセルで,
0か1をランダムにとったときに,1だった場合だけ点を打ちます.

def drawing2(img):
	for x in range(256):
		for y in range(256):
			if (random.randint(0, 1) == 1):
				draw = ImageDraw.Draw(img)
				draw.point((x, y), 0)

	return img
生成画像

f:id:yusuke_ujitoko:20150209132202j:plain

打点した数は増えてるので,上の画像よりは濃くなっていますが,
やはり規則性はなさそう.

乱数の画像化その3

今度は,一行ごとに乱数生成のseedをインクリメントします.
その2と同じように,1の時だけ打点するようにします.

def drawing3(img):
	for y in range(256):
		random.seed(y)
		for x in range(256):
			if (random.randint(0, 1) == 1):
				draw = ImageDraw.Draw(img)
				draw.point((x, y), 0)
	return img
生成画像(その3)

f:id:yusuke_ujitoko:20150209132819j:plain

やはり規則性は見つかりませんね
優秀優秀!

うーんでも,この結果だとあんまり面白く無いんだけどなあ