概述
我在工作中遇到了这个问题。
“生成的 6 位字母数字密码为 5 位,导致错误。”
我尝试使用 Python 重现此错误。
原因
只有一个随机生成的“字母数字 6 位”密码字符串是“仅 5 位”。
和“012345”一样,生成的开头是0,后面是数字,所以在与Excel文件交换的时候,好像省略了前导零,变成了“12345”。
(为什么不将它指定为 mkpasswd 的一个选项...)
发生概率
让我们计算一下这个事件发生的概率。
首先,单个数字的可能值是[0-9, a-z],所以有10+26=36种。
所以得到 0 的概率是 1/36。
另一方面,得到数字 0-9 的概率是 10/36。
这个事件是当第一个数字是0,剩下的5个数字是数字时,
(1/36) * (10/36) * (10/36) * (10/36) * (10/36) * (10/36)
= 0.0000459393658…
百分比,0.0046%。
大型银行的普通存款利率=0.001%以上的4倍。
(百分比有不同的含义)
当转换为分数时,它变为 1/21767.8。
再生产
让我们在 Python 中重现这个密码生成。
重复密码生成直到事件发生,
记录它发生了多少次,并尝试找到多次出现的平均值。
代码
import re
import random
from statistics import mean
#可変値
turns = 10
passwd_len = 6
#エラー率の計算(%)
err = 100 * (1 / 36) * (10 / 36) ** (passwd_len - 1)
'''
#ループを使って数字と小文字のリストを作成
#→固定値にしたのでコメントアウト
char_list = []
#数字
for j in range(10):
char_list.append(str(j))
#小文字アルファベット
for i in range(97, 123):
char_list.append(chr(i))
'''
#固定値。数字と小文字のリスト
char_list = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',]
#エラーになった時の試行回数を格納するリスト
challenge_count = []
print('文字列の長さ:' + str(passwd_len))
print(f'エラー率:{err:.8f}%')
print(str(round(100 / err, 1)) + '回に1回はエラーになる計算')
print('--------')
for turn in range(turns):
i = 1
while True:
passwd = ''.join(random.choices(char_list, k=passwd_len))
if passwd[0] == '0' and len(re.findall('[0-9]', passwd)) == passwd_len:
print(passwd, ': ', i, '回目')
challenge_count.append(i)
break
i += 1
print('--------')
print('試行回数 :',turn + 1)
print('最小値 :',min(challenge_count))
print('最大値 :',max(challenge_count))
print('平均値 :',mean(challenge_count))
执行结果
文字列の長さ:6
エラー率:0.00459394%
21767.8回に1回はエラーになる計算
--------
061109 : 63096 回目
085726 : 17000 回目
075952 : 9555 回目
078113 : 28085 回目
061468 : 17485 回目
042766 : 13637 回目
045780 : 9737 回目
023303 : 11550 回目
092385 : 19823 回目
039489 : 31942 回目
--------
試行回数 : 10
最小値 : 9555
最大値 : 63096
平均値 : 22191
尝试增加字符串的长度 (6 → 8)
文字列の長さ:8
エラー率:0.00035447%
282111.0回に1回はエラーになる計算
--------
09152768 : 743009 回目
01711507 : 66256 回目
09156634 : 65775 回目
09544840 : 892213 回目
09402244 : 497038 回目
05226558 : 43195 回目
00636774 : 682084 回目
09395383 : 7369 回目
07805687 : 564570 回目
02889286 : 442124 回目
--------
試行回数 : 10
最小値 : 7369
最大値 : 892213
平均値 : 400363.3
尝试增加试验次数(10 → 1000)
* 临时注释掉执行结果的打印
for turn in range(turns):
i = 1
while True:
passwd = ''.join(random.choices(char_list, k=passwd_len))
if passwd[0] == '0' and len(re.findall('[0-9]', passwd)) == passwd_len:
#print(passwd, ': ', i, '回目')
challenge_count.append(i)
break
i += 1
可以确认平均值已经接近理论值,最小值和最大值之间的波动增加了。
最少4个就很好了。
文字列の長さ:6
エラー率:0.00459394%
21767.8回に1回はエラーになる計算
--------
--------
試行回数 : 1000
最小値 : 4
最大値 : 161107
平均値 : 21707.447
印象
- 增加密码长度和尝试次数会显着增加处理时间。有必要可视化处理时间并进行修改以减轻处理。
- 经常发布彩票和扭蛋游戏的模拟器,但似乎可以应用这个程序来制作它们。
- 如果能够在图表中显示结果并对其进行分析,那就太好了,但似乎需要数学和统计知识而不是 Python 知识。
- 即使概率为 0.0046%,如果重复多次,错误总是会发生。让我们指定 mkpasswd 选项,这样它就不会发生。
mkpasswd -l 6 -d 2 -C 0 -s 0
原创声明:本文系作者授权爱码网发表,未经许可,不得转载;
原文地址:https://www.likecs.com/show-308623665.html