昨天我完成了Chris Pine的“学习计划”一书中的练习(9.5)。 它是Old-school Roman数字转换器的整数。
我就这样做了:
def old_roman_numeral number
roman_number = ""
while number != 0
if number % 1000 == 0
number -= 1000
roman_number += "M"
next
elsif number % 500 == 0
number -= 500
roman_number += "D"
next
elsif number % 100 == 0
number -= 100
roman_number += "C"
next
elsif number % 50 == 0
number -= 50
roman_number += "L"
next
elsif number % 10 == 0
number -= 10
roman_number += "X"
next
elsif number % 5 == 0
number -= 5
roman_number += "V"
next
else
number -= 1
roman_number += "I"
end
end
roman_number.reverse
end
puts "Please enter any number and I convert it to"
puts "Old-school Roman numerals."
puts
num = gets.chomp.to_i
puts "Your number #{num} converted to Old-school Roman is:"
puts (old_roman_numeral num)
当我运行脚本时,它会输出正确的罗马数字。
例如1200 => MCC
但是,当我今天醒来时,我想到的第一件事就是,这不可能是正确的! 剩下的1200%1000是200而不是0! 但是为什么输出MCC而不是CCCCCCCCCCCC
答案 0 :(得分:7)
如果您追踪该计划,它实际上首先匹配% 100 == 0
两次,获得CC
,然后留下1000.然后它匹配% 1000 == 0
,离开CCM
。最后它反转字符串,留下MCC
。
副评论:这个问题的有趣方法,因为我可能会使用一堆>=
比较来按正向顺序构建字符串,其中包含“减法”部分的特殊情况(IV
或{{ 1}})。虽然在第二次阅读时,此解决方案似乎输出IX
而不是IIII
,因此特殊情况没有实际意义。
答案 1 :(得分:0)
代码以相反的顺序计算数字。即。
首先获得C
,然后获得另一个C
,并在循环的第三次迭代中获得M
。
最后,这行代码:
roman_number.reverse
将CCM
反转为MCC
,从而获得实际获得的结果。
为了更好地了解会发生什么,您可以按如下方式更改代码:
if number % 1000 == 0
number -= 1000
roman_number += "M"
next
变为:
if number % 1000 == 0
number -= 1000
roman_number += "M"
puts "number " + number.to_s
puts "roman_number " + roman_number
next
为每个if块执行此操作。这样你就会看到每一步都会发生什么。
答案 2 :(得分:0)
不是答案,只是为了注意,这是一个具有类似目的的方法,取自我的个人图书馆:
class Numeric
RomanNumerals = {
1000 => "m", 900 => "cm", 500 => "d", 400 => "cd",
100 => "c", 90 => "xc", 50 => "l", 40 => "xl",
10 => "x", 9 => "ix", 5 => "v", 4 => "iv", 1 => "i"
}
def roman
return to_s unless 0 < self and self < 4000 # Cannot be romanized
s, r = "", self
RomanNumerals.each{|d, c| q, r = r.divmod(d); s.concat(c*q)}
s
end
end