7.3. 个案研究:罗马字母

你可能经常看到罗马数字,时时彩计划软件公式:即使你没有意识到它们。你可能曾经在老电影或者电视中看到它们 (“版权所有 MCMXLVI” 而不是 “版权所有1946”),或者在某图书馆或某大学的贡献墙上看到它们 (“成立于 MDCCCLXXXVIII”而不是“成立于1888”)。你也可能在某些文献的大纲或者目录上看到它们。这是一个表示数字的系统,它实际上能够追溯到远古的罗马帝国 (因此而得名)。

在罗马数字中,利用7个不同字母进行重复或者组合来表达各式各样的数字。

下面是关于构造罗马数字的一些通用的规则的介绍:

7.3.1. 校验千位数

怎样校验任意一个字符串是否为一个有效的罗马数字呢?我们每次只看一位数字,由于罗马数字一般是从高位到低位书写。我们从高位开始:千位。对于大于或等于 1000 的数字,千位由一系列的字符 M 表示。

例 7.3. 校验千位数

>>> import re
>>> pattern = '^M?M?M?$'       
>>> re.search(pattern, 'M')    
<SRE_Match object at 0106FB58>
>>> re.search(pattern, 'MM')   
<SRE_Match object at 0106C290>
>>> re.search(pattern, 'MMM')  
<SRE_Match object at 0106AA38>
>>> re.search(pattern, 'MMMM') 
>>> re.search(pattern, '')     
<SRE_Match object at 0106F4A8>
这个模式有三部分:
  • ^ 表示仅在一个字符串的开始匹配其后的字符串内容。如果没有这个字符,这个模式将匹配出现在字符串任意位置上的 M,而这并不是你想要的。你想确认的是:字符串中是否出现字符 M,如果出现,则必须是在字符串的开始。
  • M? 可选地匹配单个字符 M,由于它最多可重复出现三次,你可以在一行中匹配 0 次到 3 次字符 M
  • $ 字符限制模式只能够在一个字符串的结尾匹配。当和模式开头的字符 ^ 结合使用时,这意味着模式必须匹配整个串,并且在在字符 M 的前后都不能够出现其他的任意字符。
re 模块的关键是一个 search 函数,该函数有两个参数,一个是正则表达式 (pattern),一个是字符串 ('M'),函数试图匹配正则表达式。如果发现一个匹配,search 函数返回一个拥有多种方法可以描述这个匹配的对象,如果没有发现匹配,search 函数返回一个 None,一个 Python 空值 (null value)。你此刻关注的唯一事情,就是模式是否匹配上,于是我们利用 search 函数的返回值了解这个事实。字符串'M' 匹配上这个正则表达式,因为第一个可选的 M 匹配上,而第二个和第三个 M 被忽略掉了。
'MM' 能匹配上是因为第一和第二个可选的 M 匹配上,而忽略掉第三个 M
'MMM' 能匹配上因为三个 M 都匹配上了。
'MMMM' 没有匹配上。因为所有的三个 M 都匹配完了,但是正则表达式还有字符串尾部的限制 (由于字符 $),而字符串又没有结束 (因为还有第四个 M 字符),因此 search 函数返回一个 None
有趣的是,一个空字符串也能够匹配这个正则表达式,因为所有的字符 M 都是可选的。

7.3.2. 校验百位数

与千位数相比,百位数识别起来要困难得多,这是因为有多种相互独立的表达方式都可以表达百位数,而具体用那种方式表达和具体的数值有关。

  • 100 = C
  • 200 = CC
  • 300 = CCC
  • 400 = CD
  • 500 = D
  • 600 = DC
  • 700 = DCC
  • 800 = DCCC
  • 900 = CM

因此有四种可能的模式:

  • CM
  • CD
  • 零到三次出现 C 字符 (出现零次表示百位数为 0)
  • D,后面跟零个到三个 C 字符

后面两个模式可以结合到一起:

  • 一个可选的字符 D,加上零到 3 个 C 字符。

这个例子显示如何有效地识别罗马数字的百位数。

例 7.4. 检验百位数

>>> import re
>>> pattern = '^M?M?M?(CM|CD|D?C?C?C?)$' 
>>> re.search(pattern, 'MCM')            
<SRE_Match object at 01070390>
>>> re.search(pattern, 'MD')             
<SRE_Match object at 01073A50>
>>> re.search(pattern, 'MMMCCC')         
<SRE_Match object at 010748A8>
>>> re.search(pattern, 'MCMC')           
>>> re.search(pattern, '')               
<SRE_Match object at 01071D98>
这个模式的首部和上一个模式相同,检查字符串的开始 (^),接着匹配千位数 (M?M?M?),然后才是这个模式的新内容。在括号内,定义了包含有三个互相独立的模式集合,由垂直线隔开:CMCDD?C?C?C? (D是可选字符,接着是 0 到 3 个可选的 C 字符)。正则表达式解析器依次检查这些模式 (从左到右),如果匹配上第一个模式,则忽略剩下的模式。
'MCM' 匹配上,因为第一个 M 字符匹配,第二和第三个 M 字符被忽略掉,而 CM 匹配上 (因此 CDD?C?C?C? 两个模式不再考虑)。MCM 表示罗马数字1900
'MD' 匹配上,因为第一个字符 M 匹配上,第二第三个 M 字符忽略,而模式 D?C?C?C? 匹配上 D (模式中的三个可选的字符 C 都被忽略掉了)。MD 表示罗马数字 1500
'MMMCCC' 匹配上,因为三个 M 字符都匹配上,而模式 D?C?C?C? 匹配上 CCC (字符D是可选的,此处忽略)。MMMCCC 表示罗马数字 3300
'MCMC' 没有匹配上。第一个 M 字符匹配上,第二第三个 M 字符忽略,接着是 CM 匹配上,但是接着是 $ 字符没有匹配,因为字符串还没有结束 (你仍然还有一个没有匹配的C字符)。C 字符也 匹配模式 D?C?C?C? 的一部分,因为与之相互独立的模式 CM 已经匹配上。
有趣的是,一个空字符串也可以匹配这个模式,因为所有的 M 字符都是可选的,它们都被忽略,并且一个空字符串可以匹配 D?C?C?C? 模式,此处所有的字符也都是可选的,并且都被忽略。

哎呀!看看正则表达式能够多快变得难以理解?你仅仅表示了罗马数字的千位和百位上的数字。如果你根据类似的方法,十位数和各位数就非常简单了,因为是完全相同的模式。让我们来看表达这个模式的另一种方式吧。

时时彩手机投注软件 时时彩方法技巧 后二时时彩教程 彩专家时时彩计划 时时彩618注稳定大底
时时彩一星投注方法 网上重庆时时彩平台 黑客怎么改时时彩单子 重庆时时彩软件urssc 时时彩日赚300的技巧
时时彩猜单双怎么玩 后一时时彩软件 优游时时彩 灵灵发重庆时时彩 腾讯起诉易语言
新时时彩1星技巧 时时彩五星定位胆破解 金瑞期货软件 时时彩hou1杀号技巧 龙虎和时时彩高手指点
辽宁十一选五前三直走势图 河北11选5开奖结果走势图表 好彩1预测 福彩3d论坛 北京pk10计划软件
贵州快3预测号码推荐 江西多乐彩11选5走势图 排列五网站论坛 北京赛车pk10直播走 江西体彩多乐彩走势图
辽宁十一选五推荐 华夏至尊平台 网上彩票平台有哪些 浙江11选5基本走势图 江西多乐彩专家预测
"泳坛夺金"即将登陆山西 内蒙时时彩开奖彩票控 11选5倍投计划 3d试机号技巧 陕西十一选五技巧