我是 Python 新手,对模数有疑问。
这是代码:
for i in range(ord('a'), ord('z')+1):
print chr(((i+2) % 97) + 97 )
预期的结果是cdef...a
。但是,一旦我们到达z
.
因为 97 不是您想要换行的 - 您想要换行ord('z')
= 122,然后添加ord('a')
(97) 的值。
您真正需要做的全部数学运算是转换为偏移量,然后返回到集合。例如...
for i in range(ord('z') - ord('a') + 1): # equivalent to range(26); i.e. 0-25
print chr(((i+2) % 26) + ord('a')) # results in 2+97 'c', 3+97 'd', etc.
您现有代码不起作用的原因是因为您i+2
将始终大于 97(因为您i
从ord('a')
97 开始,然后从那里上升),所以% 97
实际上是 just - 97
,因此您的打印行实际上是这样的:
print chr(((i+2) - 97) + 97 )
这减少到...
print chr((i+2) - 97 + 97)
这显然只是print chr(i+2)
。
您应该以 26 为模(英文字母表中的字母数)。此代码将起作用:
for i in range(ord('a'), ord('z') + 1):
j = i - ord('a')
print chr(ord('a') + (j + 2) % 26)
考虑这个索引模板:
A + (j + B) % C
它将不同的值映射j
到 range A … (A + C - 1)
。最初,您选择了A = 97
and C = 97
,因此您将映射到 range 97 … 193
。我选择了A = ord('a') = 97
and C = 26
,所以我映射到范围97 … 122
,即ord('a') … ord('z')
。
现在关于偏移量,B
. 您想向左旋转两个位置,因此您正确选择了B = 2
. 但是,为了使它起作用,a
因为第一个字母必须0
在旋转之前进行编码。因此j = i - ord('a')
其他人已经回答了您的代码有什么问题。我想提出一个根本不需要处理模数的解决方案。我认为这是一种更简洁的方法,因为您不必处理使用 and 来回转换的ord
细节chr
。
即使您正在处理字符代码不是全部按顺序排列的外国字母,它也可以工作。
>>> from string import ascii_lowercase
>>> from collections import deque
>>> chrs = deque(ascii_lowercase)
>>> chrs.rotate(-2)
>>> print "".join(chrs)
cdefghijklmnopqrstuvwxyzab
如果您打算将其用于某种翻译或编码,只需构建一个 dict 即可:
>>> tr = dict(zip(ascii_lowercase, chrs))
>>> "".join(tr.get(x, x) for x in "abcd xyz")
'cdef zab'
在处理 mod 时,从 1 以外的数字循环可能会令人困惑。这是您的代码重构为使用 1 作为起点。
for i in range(ord('a'), ord('z')+1):
print chr( (i-97+2) % 26) + 97 ) #Subtract 97, do our modulo and shift, then add 97
您需要将值调整为 0-26 范围,修改它,应用 mod,然后移回正确的字符范围。这里有多个步骤
for i in range(ord('a'), ord('z')+1):
idx = i - ord('a')
mod_idx = ( idx + 2 ) % 26
c = chr( mod_idx + ord('a') )
print( chr(c) )
这在单行中也是一样的(IMO 太丑了)
for i in range(ord('a'), ord('z')+1):
print( chr((( i - ord('a')) + 2 ) % 26 + ord('a')) )