我正在编写一个函数来计算一段密文的卡方统计量,以确定凯撒密码最可能的密钥。
要计算卡方统计量我使用PracticalCryptography.com中的文件计算每个英文字符的相对频率并将它们存储在字典中,然后计算每个英文字母的出现次数,忽略空格和标点符号,在字符串Ciphertext
中,将它们存储在字典中,然后使用Wikipedia和PracticalCryptograhy.com中的等式计算Chi-Squared统计量。
代码:
def ChiSquared(Ciphertext):
ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
ExpOccurences = {}
with open('english_monograms.txt', 'r') as File:
for Line in File:
Key, Count = Line.split(' ')
ExpOccurences[Key] = int(Count)
for Key, Count in ExpOccurences.items():
ExpOccurences[Key] = Count / sum(ExpOccurences.values())
ActOccurences = {}
for Char in Ciphertext.upper():
if Char in ALPHABET:
if Char in ActOccurences.keys():
ActOccurences[Char] += 1
else:
ActOccurences[Char] = 1
Score = 0.0
for Char in ActOccurences.keys():
Score += (ActOccurences[Char] - (ExpOccurences[Char] * len(Ciphertext))) ** 2 / (ExpOccurences[Char])
return Score
我的问题是每次我用相同的字符串调用函数时,我得到一个不同的Score
。为什么会发生这种情况,我该如何预防/修复它?我应该硬编码频率吗?是否由于计算相对频率时出现下溢误差?
不一致的例子:
>>> ChiSquared('HELLO WORLD')
139.3055836714786
>>>
>>> ChiSquared('HELLO WORLD')
140.48594498993816
>>>
>>> ChiSquared('HELLO WORLD')
132.3702317119948
>>>
>>> ChiSquared('HELLO WORLD')
65.840138355439
>>>
>>> ChiSquared('HELLO WORLD')
129.22608450306808
>>>