我是Ruby的新手,我正在尝试编写一个将罗马数字转换为数字的程序。
这是我到目前为止所做的:
roman_numbers = {"M" => 1000, "D" => 500, "C" => 100, "L" => 50, "X" => 10, "V" => 5, "I" => 1}
number_by_user = "MCMXCIX"
singlenum = number_by_user.split(//).reverse!
l = singlenum.length
result =0
result = roman_numbers[singlenum[0]]
puts result
for i in 0..l-1
if roman_numbers.key?(singlenum[i])
**if (roman_numbers[singlenum[i]] > roman_numbers[singlenum[i+1]])** #gives error
result = result - roman_numbers[singlenum[i+1]]
elsif (roman_numbers[singlenum[i]]== roman_numbers[singlenum[i+1]] || **roman_numbers[singlenum[i]] < roman_numbers[singlenum[i+1]])** #gives error
result = result + roman_numbers[singlenum[i+1]]
end
puts roman_numbers[singlenum[i]]
else
puts "One of the values are not roman"
break
end
end
puts "The number is: " , result
但它给了我以下错误(请参阅注释行):
:in `>': comparison of Fixnum with nil failed (ArgumentError)
答案 0 :(得分:5)
您有一个错误的错误。数组为0索引。在这种情况下,您的singlenum.length
为7,但在for循环中,您最多为6,然后尝试引用singlenum[7]
与singlenum[6]
进行比较。 singlenum[7]
是nil
,因此它不理解&lt;操作
答案 1 :(得分:4)
Marc很好地解释了代码中的错误。但是,首先应该永远不会发生这样的错误,因为在Ruby中,所有集合都已经知道如何迭代自己:你不必这样做,所以你永远不能< em> make 这样的错误!
以下是一个如何在更惯用的Ruby中实现相同算法的示例:
numerals = {
'M' => 1000,
'D' => 500,
'C' => 100,
'L' => 50,
'X' => 10,
'V' => 5,
'I' => 1
}
num = 'MCMXCIX'
(num.chars.map(&numerals.method(:[])) << 0).each_cons(2).inject(0) {|a, (n1, n2)|
if n1 < n2 then a - n1 else a + n1 end
}
请参阅?没有循环。没有指数。即使您尝试了,也无法发出一个错误的错误!
Bonus:实际上,上面的代码片段 包含一段代码以防止出现一个错误,尽管语义级别要高得多。你能找到吗?