在`>':在Ruby中将Fixnum与nil失败(ArgumentError)Roman Numeral转换器进行比较

时间:2012-02-24 23:19:04

标签: ruby

我是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)

2 个答案:

答案 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:实际上,上面的代码片段 包含一段代码以防止出现一个错误,尽管语义级别要高得多。你能找到吗?