Ruby 余数-我的代码不正确,但它为什么工作?

Ruby 余数-我的代码不正确,但它为什么工作?,ruby,Ruby,昨天我完成了Chris Pine的《学习编程》一书中的一个练习(9.5)。 这是一个整数到老式罗马数字的转换器 我就是这样做的: def old_roman_numeral number roman_number = "" while number != 0 if number % 1000 == 0 number -= 1000 roman_number += "M" next

昨天我完成了Chris Pine的《学习编程》一书中的一个练习(9.5)。 这是一个整数到老式罗马数字的转换器

我就是这样做的:

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而不是cccc???

如果你跟踪整个程序,它实际上是先匹配两次
%100==0
,得到
CC
,剩下1000。然后它匹配
%1000==0
,留下
CCM
。最后,它反转字符串,留下
MCC



旁注:解决这个问题的有趣方法,因为我可能会使用大量的
=
比较,将字符串按“减法”部分(
IV
IX
)的特殊情况向前构建。尽管在二读时,此解决方案似乎输出的是
IIII
,而不是
IV
,因此特殊情况没有意义。

代码按相反顺序计算数字。i、 e

首先得到一个
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块执行此操作。通过这种方式,您将看到每个步骤中发生的情况。

不是答案,但请注意,这里有一个类似的方法,取自我的个人图书馆:

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
类数值
罗马数字={
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”
}
迪夫罗曼
除非0
ahhh,现在我看到了!很容易。非常感谢你的澄清!第一个练习(这一个)是没有减法的古罗马风格。下一个是减法。旁注:你可以尝试一种更为数学化的方法(不使用
roman_number=“”
-=
+=
),这将是一个很好的练习。@tokland是的,我已经阅读了本书末尾的Chris Pine的解决方案。它更优雅、更高效。。。