简体   繁体   English

Rot13和使用模数

[英]Rot13 and the use of the modulo

I've been reading "Think Python" by Allen B. Downey and there's an exercise (8.12) in it where the author asks to create a ROT13 function. 我一直在阅读Allen B. Downey的“ Think Python”,其中有一个练习(8.12),作者要求创建ROT13函数。 I did mine and it partially worked because I was struggling with the uppercases. 我做了我的,并且部分奏效了,因为我在用大写字母挣扎。

Here's a part of the solution provided by the author: 这是作者提供的解决方案的一部分:

def rotate_letter(letter, n):
"""Rotates a letter by n places.  Does not change other chars.

letter: single-letter string
n: int

Returns: single-letter string
"""
if letter.isupper():
    start = ord('A')
elif letter.islower():
    start = ord('a')
else:
    return letter

c = ord(letter) - start
i = (c + n) % 26 + start
return chr(i)

The use of the modulo here makes the function work for the uppercases but I can't figure why ! 此处使用模数使该函数适用于大写字母,但我不知道为什么! It's clear that by using it we restart at the beginning of the ASCII values for uppercase but I can't figure the mechanism behind it. 显然,通过使用它,我们以大写的ASCII值的开头重新启动,但是我无法弄清楚其背后的机制。

Try breaking it down into steps, and printing out the intermediate numbers. 尝试将其分解为多个步骤,然后打印出中间数字。 Or, better, running it in an online visualizer . 或者,最好在联机可视化工具中运行它。

With, say, the letter 'Q' and the number 13, you'll end up with: 例如,使用字母'Q'和数字13,您将得到:

'Q'.isupper() is true
start = ord('A') = 65
c = ord('Q') - start = 81 - 65 = 16
i = (c + n) % 26 + start = (16 + 13) % 26 + 65 = 29 % 26 + 65 = 3 + 65 = 68
chr(i) is 'D'

As you can see, the magic part is that (16 + 13) % 26 . 如您所见,最神奇的部分是(16 + 13) % 26 So let's try running that on every one of the numbers from 0 (for A ) to 25 (for Z ) and see what happens: 因此,让我们尝试在从0(对于A )到25(对于Z )的每个数字上运行它,然后看看会发生什么:

>>> for i in range(26):
...     print ((i + 13) % 26),
13 14 15 16 17 18 19 20 21 22 23 24 25 0 1 2 3 4 5 6 7 8 9 10 11 12

Adding, then taking the remainder with 26, means that when you get to 26 you go back around to 0. Just like adding 1 hour to 23:00 gets you to 00:00 on a clock (or, if you're an American, adding 1 hour to 12:00 gets you to 1:00). 加法,然后将余数乘以26,则意味着当您达到26时,您将回到零。就像将1小时加到23:00会使您在时钟上达到00:00(或者,如果您是美国人,则将1小时加到12:00会使您达到1:00)。

The modulo 26 has nothing to do with uppercase and lowercase per se, it's needed to make the sequence wrap back to the beginning. 模26本身与大写和小写无关,需要使序列回绕到开头。

Consider a simple "rot 1": treat the letters of the alphabet as numbers from 1 to 26, and add 1. If the input is 'a', you take 1+1=2 and get 'b'; 考虑一个简单的“ rot 1”:将字母视为从1到26的数字,然后加1。如果输入为'a',则取1 + 1 = 2并得到'b';如果输入为'a',则取1 + 1 = 2。 if the input is 'z', you take 26+1=27 - but there's no 27th letter of the alphabet! 如果输入为“ z”,则取26 + 1 = 27-但是没有27个字母! So you calculate 27 mod 26 = 1, which "rotates" back to 'a'. 因此,您计算出27 mod 26 = 1,它将“旋转”回'a'。

The actual trick for upper and lowercase in the implementation above is the definition of start , which turns ASCII positions into numbers 1 to 26 before applying the rotation, then turns the result back using the same offset. 在上面的实现中,大小写的实际技巧是start的定义,该定义在应用旋转之前将ASCII位置转换为数字1到26,然后使用相同的偏移量将结果返回。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM