我是Python的新手,并且模数有问题。
以下是代码:
for i in range(ord('a'), ord('z')+1):
print chr(((i+2) % 97) + 97 )
检测到的结果为cdef...a
。但是,一旦到达z
,我就无法获得所需的模块行为。
答案 0 :(得分:6)
因为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
实际上只是- 97
,因此您的打印行实际上是这样的:
print chr(((i+2) - 97) + 97 )
减少到......
print chr((i+2) - 97 + 97)
显然只是print chr(i+2)
。
答案 1 :(得分:3)
你应该使用模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
的不同值映射到范围A … (A + C - 1)
。最初,您选择了A = 97
和C = 97
,因此您要映射到范围97 … 193
。我选择了A = ord('a') = 97
和C = 26
,因此我映射到范围97 … 122
,即ord('a') … ord('z')
。
现在关于偏移B
。您想要向左旋转两个位置,因此您已正确选择B = 2
。但是,为了使其正常工作,a
作为第一个字母必须在轮换之前由0
编码。因此j = i - ord('a')
答案 2 :(得分:1)
您需要将值调整为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) )
这就是oneline(太丑陋的IMO)
for i in range(ord('a'), ord('z')+1):
print( chr((( i - ord('a')) + 2 ) % 26 + ord('a')) )
答案 3 :(得分:1)
在处理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
答案 4 :(得分:1)
其他人已经回答了您的代码有什么问题。我想提出一个不必处理模数的解决方案。我认为这是一种更简洁的方法,因为您不必处理使用ord
和chr
来回转换的细节。
即使您正在处理字符代码并非全部按顺序排列的外国字母表,它也可以正常工作。
>>> from string import ascii_lowercase
>>> from collections import deque
>>> chrs = deque(ascii_lowercase)
>>> chrs.rotate(-2)
>>> print "".join(chrs)
cdefghijklmnopqrstuvwxyzab
如果您打算将其用于某种翻译或编码,只需构建一个词典然后离开:
>>> tr = dict(zip(ascii_lowercase, chrs))
>>> "".join(tr.get(x, x) for x in "abcd xyz")
'cdef zab'