第六章 单元测试

目录

6.1. 接触

在前一章,我们的“研究”是通过马上查看代码,并努力以最快的速度进行理解。即然你已经有了一些Python的经验,我们将回过头来,看一看在编码之前所发生的步骤。

本章我们将编写一组实用函数,用于罗马数字的转换。你很有可能已经看过罗马数字,尽管不认识它们。你可能在老电影电视节目中的版权信息中看到过(“Copyright MCMXLVI”而不是“Copyright 1946”),或在图书馆或大学的贡献人名围墙上看到过(“established MDCCCLXXXVIII”而不是“established 1888”)。也可能你在参考书的提纲或目录中看到过。它是一种数字表示系统,这种表示真正地让我们回到古罗马时代(由此而得名)。

在罗马数字中,有七个字符,它们以各种各样的方法进行重复和组合,用来表示数字。

  1. I = 1
  2. V = 5
  3. X = 10
  4. L = 50
  5. C = 100
  6. D = 500
  7. M = 1000

构造罗马数字有一些通用的规则:

  1. 字符是一个加在一个后面。I1II2III3VI6 (按字面意思,“51”),VII7VIII8
  2. 10 的倍数字符(IXC,和M)最多可以重复 3 次。到了第 4 次,你必须从接着的最大的 5 的倍数字符作减法。你不能用 IIII 表示 4;而应该用 IV 来表示(5 1)。40 被写作 XL5010),41XLI42XLII43XLIII44XLIV(“ 5010,然后 51)。
  3. 同样,对于 9,你必须从接着的最大的 10 的倍数字符作减法:8VIII,但 9IX (“101”),不是 VIIII (因为 I 字符不能被重复 4 次)。90XC900CM
  4. 5 的倍数字符不能被重复,10 总是表示为 X,决不会为 VV100 总是 C,决不会为 LL
  5. 罗马数字总是从最高到最低,从左向右读,所以字符的顺序非常重要。DC600CD 是一个完全不同的数字(400,“500100”)。 CI101IC 甚至不是一个有效的罗马数字(因为你不能从 100 直接减 1;应该写成 XCIX,“10010 ,接着101”)。

这些规则可以得出许多有趣的观察结果:

  1. 仅有一种正确的方法将一个数字表示为罗马数字。
  2. 反过来也是对的:如果一个字符串是一个有效的罗马数字,它只表示一个数字(也就是,它只能以一种方式读出来)。
  3. 用罗马数字能够表达有限范围的数字,明确为 13999。(罗马人的确有几种方法表达更大的数字,例如在数字上加一道表示这个值应乘上 1000,但我们不打算这样处理。出于本章的目的,罗马数字是从 13999。)
  4. 在罗马数字中没有 0 的表示。(真令人吃惊,古罗马人不把 0 看成一个数字。数字是用来对你的东西进行数数用的;你怎么能数你没有的东西呢?)
  5. 用罗马数字没有方法表示负数。
  6. 用罗马数字没有方法表示小数或分数。

知道这些以后,我们希望写出一套什么样的函数进行罗马数字的转换呢?

roman.py 的要求

  1. toRoman 应该返回所有从 13999 的数字的罗马数字表示。
  2. 当所给的整数超出 13999 时,toRoman 应该失败。
  3. 当给出一个非整数时,toRoman 应该失败。
  4. fromRoman 应该接收一个有效的罗马数字,并返回它所表示的数字。
  5. 当给出一个无效的罗马数字时,fromRoman 应该失败。
  6. 如果你接收一个数字,将其转换成罗马数字,接着再转换回数字,最后应该是开始时的数字。所以对所有在 13999 中的 nfromRoman(toRoman(n)) == n
  7. toRoman 应该总是返回使用大写字母的罗马数字。
  8. fromRoman 应该只接收大写罗马数字(也就是当给出小写输入时,它应该出错)。

进一步阅读

  • 这个站点 有更多的关于罗马数字的内容,它包括了罗马迷人的历史和其它文明是如何真正使用它们的(简单地说:偶然的和不一致的)。