[Python]模拟6位字母数字字符变成5位的问题

概述

我在工作中遇到了这个问题。“生成的 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

39人参与, 0条评论 登录后显示评论回复

你需要登录后才能评论 登录/ 注册