0
1

pythonで真性乱数を使う。

Last updated at Posted at 2023-09-18

真性乱数を取り出すpythonのモジュールです。

コンピュータで使える乱数は、2種類あり、周期をもつ疑似乱数と、統計論的に正しい真性乱数があります。他に、コンピュータで扱えない「完全乱数」というものも存在し、確率的にしか扱うことは出来ません。

python3では、乱数の利用は主にrandomモジュールを使いますが、これは、疑似乱数を発生するもので、真の乱数ではありません。しかし、Linuxは、/dev/randomを提供していて、これを読み出すと、環境ノイズからの真性乱数を得ることができるので、これを使います。

「真性乱数」は「完全乱数」と定義が違います。

・真性乱数とは、原理的に予測不能で真に無秩序な乱数。コンピューターによって算術的に生成する疑似乱数に対していう。放射性元素の崩壊など、量子的なふるまいを利用する物理乱数が知られる。真乱数。- 小学館 - デジタル大辞泉より。

・完全乱数とは、完全にでたらめな順番で発生する数値の列を指し、理想の乱数とも呼ばれます。確率的にしか扱うことができません。 - Search Labs | AIによる。

定義が違いますが、実用上は、真性乱数を完全乱数と看做して、同様に扱って良いでしょう。

/dev/randomは一回の読み出しで1バイトを返します。

メソッドの説明

rand(n)はn*8ビット正の整数の範囲の真性乱数を返します。

rand_f(n)は、実用的に、[0,1)のfloat型の乱数を返しますが、乱数の分布は実数のように連続ではありませんし、整数同士の割り算を1回行っているため、真性乱数ではなくなっています。

randomint(k,n)は、実用的に0~n-1の整数乱数を返しますが、剰余計算を行っているため、真性乱数ではなくなっています。

truerand.py
#!/usr/bin/python3
#
# truerand.py
# pythonで、/dev/randomからの真性乱数を利用して乱数を発生するモジュール
#
import os
import binascii

# n byteのRAND_MAXを返す関数
# in : n バイト長
# out: nバイトのRAND_MAX
def rand_max(n):
    v=0
    for i in range (0,n):
        v=v*256+0xff
    return(v)

# n byte の真性乱数を返す関数
# parameter : n バイト長
# return    :   n バイトの正の整数の乱数
def rand(n):
    f=open("/dev/random",'rb') # /dev/randomを開く
    randomdata=f.read(n) # nバイト読み出し
    f.close() # /dev/randomを閉じる
    randomhex=binascii.hexlify(randomdata) #16進の文字列に変換
    randomint=int(randomhex,16) # 整数に変換
    return(randomint)

#
# n byte の精度の[0,1)の実数乱数を返す関数
# parameter : n バイト長
# return    : [0,1)の乱数
#
# 注:割り算を使っているので本当の真性乱数ではない
#
def rand_f(n):
    return(rand(n)/rand_max(n))

#
# 0〜k-1の乱数を返す関数
# parameters : n バイト長
               k 整数
# return     : 0〜(k-1)の整数乱数
#
# 注:剰余演算を使っているので本当の真性乱数ではない
#
def randomint(k,n):
    return(rand(n)%k)

if __name__=="__main__":
    b=8
    times=20
    print(f"{b*8}bit正の真性整数乱数")
    for _ in range(times):
        print(rand(b),end=" ")

    print("")
    print("実数[0,1)の範囲の実数乱数")
    for _ in range(times):
        print(rand_f(b),end=" ")
    print("")
    print("整数0〜99の乱数")
    for _ in range(times):
        print(randomint(100,b),end=" ")
    print("")

実行結果

$ truerand.py
64bit正の真性整数乱数
3307504999628493041 16833230142106673071 12617132537912657723 13507463181985722647 10497082142665300591 6631042183926931135 15360962062758597424 13993642308568418315 766978283825206867 10039168542496294747 5012398474653242549 2895278196839792201 14818507220427785701 12973819612571874604 745060180634753097 3407469691878957494 16057494043478543453 17702076263089849866 6044349191818680689 18016755088876227617 
実数[0,1)の範囲の実数乱数
0.7974003807166161 0.41979958470339007 0.5609974574080073 0.867573227719673 0.4440622865950301 0.6675132571776963 0.6540182828071875 0.3561816976682385 0.8544635154444369 0.14384499913999788 0.6299092884789043 0.8762444099735378 0.12412862806208831 0.9767549851060453 0.7885647613995059 0.20188391849163984 0.42782772905419625 0.10491103155813546 0.8019370785707318 0.43197777323789693 
整数0〜99の乱数
70 33 45 38 39 88 79 9 90 38 36 43 5 49 74 81 56 71 31 29 
$
0
1
1

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
0
1