/dev/random のランダム性をテストする Python スクリプトを作成しようとしていますが、数値を取得できません。私のコードは次のようになります
with open("/dev/random", 'rb') as file:
print f.read(10)
/dev/random から 10 バイトを出力すると思われますが、数字の代わりに奇妙な文字 (非標準の文字と数字なし) を出力します。私が間違っていることは何か分かりますか?
/dev/random のランダム性をテストする Python スクリプトを作成しようとしていますが、数値を取得できません。私のコードは次のようになります
with open("/dev/random", 'rb') as file:
print f.read(10)
/dev/random から 10 バイトを出力すると思われますが、数字の代わりに奇妙な文字 (非標準の文字と数字なし) を出力します。私が間違っていることは何か分かりますか?
Python にはこのための組み込み関数があります (他の OS でも適切なメソッドを使用します)...
import os
print os.urandom(10)
# '\xf1\x11xJOl\xab\xcc\xf0\xfd'
http://docs.python.org/2/library/os.html#os.urandomのドキュメントから
この関数は、OS 固有の乱数ソースから乱数バイトを返します。返されるデータは、暗号化アプリケーションにとって十分に予測不可能である必要がありますが、その正確な品質は OS の実装によって異なります。UNIX ライクなシステムでは、これは /dev/urandom を照会し、Windows では CryptGenRandom を使用します。乱数ソースが見つからない場合、NotImplementedError が発生します。
これらのバイトを数値にしたい場合は、次のように変換することで実行できます。
>>> rand = os.urandom(10)
>>> int(binascii.hexlify(rand), 16)
1138412584848598544216317L
または Python 2 を使用:
>>> int(rand.encode('hex'), 16)
1138412584848598544216317L
とはわずかに異なるため/dev/random
、違いが重要な場合は、/dev/urandom
既存の.read()
op を使用して変換を行うことができます。int
10 バイトを取得しています。Python はそれらを自動的に数値に変換しません。
バイトを 4 の倍数で取得し、それらを 32 ビットの符号なし整数に変換し、必要に応じてスケーリングすることをお勧めします。
EDIT:古いコードはアイデアを示していましたが、機能にうまく分割されていませんでした。これは基本的な考え方は同じですが、便利に関数にパッケージ化されています。
import os
import struct
_random_source = open("/dev/random", "rb")
def random_bytes(len):
return _random_source.read(len)
def unpack_uint32(bytes):
tup = struct.unpack("I", bytes)
return tup[0]
UINT32_MAX = 0xffffffff
def randint(low, high):
"""
Return a random integer in the range [low, high], including
both endpoints.
"""
n = (high - low) + 1
assert n >= 1
scale_factor = n / float(UINT32_MAX + 1)
random_uint32 = unpack_uint32(random_bytes(4))
result = int(scale_factor * random_uint32) + low
return result
def randint_gen(low, high, count):
"""
Generator that yields random integers in the range [low, high],
including both endpoints.
"""
n = (high - low) + 1
assert n >= 1
scale_factor = n / float(UINT32_MAX + 1)
for _ in range(count):
random_uint32 = unpack_uint32(random_bytes(4))
result = int(scale_factor * random_uint32) + low
yield result
if __name__ == "__main__":
# roll 3 dice individually with randint()
result = [randint(1, 6) for _ in range(3)]
print(result)
# roll 3 dice more efficiently with randint_gen()
print(list(randint_gen(1, 6, 3)))
ランダムな文字を出力しているので、ord()
関数を使用してそれらを int に変換するだけです。何かのようなもの:
with open("/dev/random", 'rb') as file: print [ord(x) for x in file.read(10)]
これにより、0 から 255 までの 10 個のランダムな int のリストが出力されます (取得した: [117, 211, 225, 24, 134, 145, 51, 234, 153, 89]
)。