Eine schnelle und tragbare Lösung:
from zlib import crc32
def bytes_to_float(b):
return float(crc32(b) & 0xffffffff)/2**32
Dieser wandelt ein Byte-String in einen Schwimmer zwischen 0,0 und 1,0. Wenn Sie einen Unicode-String verwenden (zB in Python 3), dann müssen Sie es kodieren:
def str_to_float(s, encoding="utf-8"):
return bytes_to_float(s.encode(encoding))
Beispiel
>>> str_to_float(u"café")
0.5963937465567142
Dies sollte das gleiche Ergebnis auf jeder Maschine geben und jede Version von Python (getestet auf Python 2.7 und 3.5).
Hinweis: Die & 0xffffffff
ist hier, um ein vorzeichenloses int-Ergebnis zu garantieren. Es wird benötigt, da abhängig von der Python-Version crc32(b)
eine signed oder unsigned int zurückgeben kann.
bearbeiten
Wenn Sie etwas mehr "zufällig" als ein CRC32, können Sie stattdessen, wie SHA256 eine Hash-Funktion verwenden:
from struct import unpack
from hashlib import sha256
def bytes_to_float(b):
return float(unpack('L', sha256(b).digest()[:8])[0])/2**64
Leistungstest
String length
Function 7 70 700 7000
b2f_crc32 0.34 0.38 0.87 5.59
b2f_md5 0.96 1.08 2.11 11.13
b2f_sha1 0.99 1.07 1.76 8.37
b2f_sha256 1.11 1.20 2.60 16.44
b2f_rnd 6.59 6.55 6.59 6.60
Grundsätzlich ist die CRC32-Lösung mit Abstand die schnellste für kurze Strings (18x schneller als @ user3030010's random = RND-Lösung). Es ist ungefähr 3x schneller als SHA256, unabhängig von der Saitenlänge. SHA256 ist langsamer als MD5, was langsamer als SHA1 ist (außer für sehr kurze Strings). Wie auch immer, die RND-Option hängt nicht von der String-Länge ab. Wenn die Strings sehr lang sind, kann es die schnellste Option sein (siehe meine Kommentare zu @ user3030010): auf meinem Computer schlägt es SHA256 für Strings länger als 2500 Zeichen, und es schlägt CRC32 für Strings länger als 8000 Zeichen.
Hier ist der Code, mit timeit.timeit()
:
from __future__ import print_function
[...] # define b2f_crc32, b2f_md5 and so on.
for func in ("b2f_crc32", "b2f_md5", "b2f_sha1", "b2f_sha256", "b2f_rnd"):
for length in (7, 70, 700, 7000):
t = timeit('b2f(b"%s")'%(b"x"*length),
'from __main__ import %s as b2f' % func)
print("%.2f"%t, end="\t")
print()
Wenn ich gut verstehen, random.seed() nur den Generator initialisiert aber nicht wieder etwas? – Vincent
@Vincent Das ist richtig. Aber es beeinflusst die Reihenfolge der Werte, die von 'random.random()' zurückgegeben werden. Die erste Zufallszahl hängt also direkt vom Seed ab. – Barmar
Diese Antwort ist interessant, aber es gibt zwei Einschränkungen: Erstens kann es abhängig von der Python-Installation unterschiedliche Ergebnisse zurückgeben, da 'hash' möglicherweise andere Ergebnisse über Python-Installationen zurückgibt. Zweitens ändert sich der gemeinsame Random Seed. Wenn also andere Teile des Programms auf Zufallszahlen beruhen, kann dies negative Auswirkungen haben. Ich würde entweder meine Antwort empfehlen oder zumindest 'random.seed (hash (your_string))' mit 'rnd = random ersetzen.Random (your_string) ', dann' rnd.random() '. – MiniQuark