Как мы можем честно подбросить миллиард монет и написать свое имя криптовалютой?
Допустим, у нас есть один миллиард человек, которые участвуют в соревновании. У нас есть один бросок монеты, и если вы его угадаете, вы продолжите. Если нет, значит, вы выбываете из конкурса. Сколько бросков потребуется, чтобы получить победителя (в среднем)?
Думаю, потребуется всего… 30 раундов (я спросил кого-то раньше, и они сказали, что это один триллион!).
Таким образом, из одного миллиарда человек у нас было бы 30 подбрасываний монеты, и у нас (в среднем) был бы победитель. Согласен ли ты со мной?
Быстрые случайные числа
Итак, как мы собираемся построить компьютер, который будет быстро создавать один миллиард случайных чисел? Что ж, в 2016 году появился Xoroshiro128 +, у которого есть время менее наносекунды для каждого сгенерированного случайного числа. Таким образом, мы могли бы сгенерировать один миллиард случайных чисел менее чем за секунду. Но как нам просто немного перевернуть? Ну, мы просто замаскируем младший бит.
Итак, давайте возьмем два начальных значения и сгенерируем первые 10 случайных значений и первые 50 бросков:
import sys val1=54253124354024L val2=5395042653908L def bin2chr(data): result = '' while data: char = data & 0xff result += chr(char) data >>= 8 return result class Xoroshiro128Plus(object): def __init__(self, seed): self.seed = seed @staticmethod def rotl(x, k): return ((x << k) & 0xffffffffffffffff) | (x >> 64 - k) def next(self): s0 = self.seed[0] s1 = self.seed[1] result = (s0 + s1) & 0xffffffffffffffff s1 ^= s0 self.seed[0] = self.rotl(s0, 55) ^ s1 ^ ((s1 << 14) & 0xffffffffffffffff) self.seed[1] = self.rotl(s1, 36) return result print "Seed 1:\t",val1 print "Seed 2:\t",val2 print generator = Xoroshiro128Plus([val1, val2]) for i in range(4): val=generator.next() print hex(val),'\t', print(repr(bin2chr(val)))
Прогон дает:
Seed 1: 54253124354024 Seed 2: 5395042653908 0 0x363febce56bcL '\xbcV\xce\xeb?6' 1 0xb44a630c2a0b0f01L '\x01\x0f\x0b*\x0ccJ\xb4' 2 0x35b971bef18473e6L '\xe6s\x84\xf1\xbeq\xb95' 3 0x9497b673f320d89bL '\x9b\xd8 \xf3s\xb6\x97\x94' 4 0xd07401ef48e22e0L '\xe0"\x8e\xf4\x1e@\x07\r' 5 0xdcc0618d77a1ce2bL '+\xce\xa1w\x8da\xc0\xdc' 6 0xd719917970062c09L '\t,\x06py\x91\x19\xd7' 7 0xacd2ed2c5461b336L '6\xb3aT,\xed\xd2\xac' 8 0xc619e5ac2efae9e7L '\xe7\xe9\xfa.\xac\xe5\x19\xc6' 9 0x4bfbdf8610735319L '\x19Ss\x10\x86\xdf\xfbK' Coin flip (60) H T H T H T T H T T T T T H T T H H H H H T T H T H T T T H T T T H T T H H H T H T H T H T T T H T T T H T H T H H T H Heads: 26 Tails: 34
Мы видим, что у нас 26 орлов и 34 решки, что не является 50/50, но оно начнет стремиться к разделению 50/50, когда у нас будет достаточно бросков. Пример выполнения здесь:
В следующем коде мы берем случайные числа, а затем маскируем наименее значимый бит и определяем его как «Голова» или «Хвост»:
import sys val1=54253124354024L val2=5395042653908L if (len(sys.argv)>1): val1=int(sys.argv[1]) if (len(sys.argv)>2): val2=int(sys.argv[2]) def bin2chr(data): result = '' while data: char = data & 0xff result += chr(char) data >>= 8 return result class Xoroshiro128Plus(object): def __init__(self, seed): self.seed = seed @staticmethod def rotl(x, k): return ((x << k) & 0xffffffffffffffff) | (x >> 64 - k) def next(self): s0 = self.seed[0] s1 = self.seed[1] result = (s0 + s1) & 0xffffffffffffffff s1 ^= s0 self.seed[0] = self.rotl(s0, 55) ^ s1 ^ ((s1 << 14) & 0xffffffffffffffff) self.seed[1] = self.rotl(s1, 36) return result print "Seed 1:\t",val1 print "Seed 2:\t",val2 print generator = Xoroshiro128Plus([val1, val2]) for i in range(10): val=generator.next() print i,hex(val),'\t', print(repr(bin2chr(val))) print '\nCoin flip' generator = Xoroshiro128Plus([val1, val2]) count=0 for i in range(50): val=generator.next() bit = val & 0x1 if (bit==0): count = count+1 print "H", else: print "T", print print 'Heads:\t',count print 'Tails:\t',50-count
Написание своего имени в криптовалюте
А пока мы используем Xoroshiro128 +, давайте немного повеселимся. Знали ли вы, что на самом деле можно взломать генератор случайных чисел, чтобы отображалось мое имя (Попробовать):
Seed 1: 11000710321405755819 Seed 2: 15528335171484875594 0 0x702a1a51a1ec7cf5L ‘\xf5|\xec\xa1Q\x1a*p’ 1 0x7562206c6c6962L ‘bill bu’ 2 0x6d206e616e616863L ‘chanan m’ 3 0x5d92516ca1be5e56L ‘V^\xbe\xa1lQ\x92]’ 4 0x26028de6210a115aL ‘Z\x11\n!\xe6\x8d\x02&’ 5 0x6e2e21263ba96777L ‘wg\xa9;&!.n’ 6 0x14104cb7e79dc043L ‘C\xc0\x9d\xe7\xb7L\x10\x14’ 7 0x6b137d1ba15b5528L ‘(U[\xa1\x1b}\x13k’ 8 0xab954c20376230cdL ‘\xcd0b7 L\x95\xab’ 9 0xe5cce6246f6c38eL ‘\x8e\xc3\xf6Fb\xce\\\x0e’ Coin flip (60) T H T H H T T H T H H T H H H T H H T T H H T H H H H T H T H T T T T H H H T T H H H T H H H H H H H T H T T H H H H H Heads: 38 Tails: 22
Как я это сделал? Можете ли вы придумать, как написать собственное имя?
Выводы
Миллиард человек ... и 30 раундов ... и у нас есть победитель. Правда или ложь?
Вы тоже можете написать свое имя криптовалютой?