使用Ruby将数字转换为单词?

时间:2013-10-18 08:29:44

标签: ruby-on-rails ruby numbers

如何将数字转换为ruby中的单词?

我知道某处有一颗宝石。试图在没有宝石的情况下实现它。我只需要用英语单词的数字来表示整数。发现这个,但它非常混乱。如果您对如何实现更清晰易读的解决方案有任何想法,请分享。

http://raveendran.wordpress.com/2009/05/29/ruby-convert-number-to-english-word/

这是我一直在做的事情。但在实施量表时遇到一些问题。代码仍然是一团糟。我希望它在正常运行时更具可读性。

   class Numberswords
    def in_words(n)

    words_hash = {0=>"zero",1=>"one",2=>"two",3=>"three",4=>"four",5=>"five",6=>"six",7=>"seven",8=>"eight",9=>"nine",
                    10=>"ten",11=>"eleven",12=>"twelve",13=>"thirteen",14=>"fourteen",15=>"fifteen",16=>"sixteen",
                     17=>"seventeen", 18=>"eighteen",19=>"nineteen",
                    20=>"twenty",30=>"thirty",40=>"forty",50=>"fifty",60=>"sixty",70=>"seventy",80=>"eighty",90=>"ninety"}

     scale = [000=>"",1000=>"thousand",1000000=>" million",1000000000=>" billion",1000000000000=>" trillion", 1000000000000000=>" quadrillion"]


    if words_hash.has_key?(n) 
      words_hash[n]

      #still working on this middle part. Anything above 999 will not work
     elsif n>= 1000  
     print  n.to_s.scan(/.{1,3}/) do |number|
            print number
      end



      #print value = n.to_s.reverse.scan(/.{1,3}/).inject([]) { |first_part,second_part| first_part << (second_part == "000" ? "" : second_part.reverse.to_i.in_words) }
      #(value.each_with_index.map { |first_part,second_part| first_part == "" ? "" : first_part + scale[second_part] }-[""]).reverse.join(" ")

    elsif n <= 99
       return [words_hash[n - n%10],words_hash[n%10]].join(" ")
    else
      words_hash.merge!({ 100=>"hundred" })
      ([(n%100 < 20 ? n%100 : n.to_s[2].to_i), n.to_s[1].to_i*10, 100, n.to_s[0].to_i]-[0]-[10])
        .reverse.map { |num| words_hash[num] }.join(" ")
    end
  end
end

#test code
test = Numberswords.new
 print test.in_words(200)

8 个答案:

答案 0 :(得分:17)

我对此的看法

def in_words(int)
  numbers_to_name = {
      1000000 => "million",
      1000 => "thousand",
      100 => "hundred",
      90 => "ninety",
      80 => "eighty",
      70 => "seventy",
      60 => "sixty",
      50 => "fifty",
      40 => "forty",
      30 => "thirty",
      20 => "twenty",
      19=>"nineteen",
      18=>"eighteen",
      17=>"seventeen", 
      16=>"sixteen",
      15=>"fifteen",
      14=>"fourteen",
      13=>"thirteen",              
      12=>"twelve",
      11 => "eleven",
      10 => "ten",
      9 => "nine",
      8 => "eight",
      7 => "seven",
      6 => "six",
      5 => "five",
      4 => "four",
      3 => "three",
      2 => "two",
      1 => "one"
    }
  str = ""
  numbers_to_name.each do |num, name|
    if int == 0
      return str
    elsif int.to_s.length == 1 && int/num > 0
      return str + "#{name}"      
    elsif int < 100 && int/num > 0
      return str + "#{name}" if int%num == 0
      return str + "#{name} " + in_words(int%num)
    elsif int/num > 0
      return str + in_words(int/num) + " #{name} " + in_words(int%num)
    end
  end
end



puts in_words(4) == "four"
puts in_words(27) == "twenty seven"
puts in_words(102) == "one hundred two"
puts in_words(38_079) == "thirty eight thousand seventy nine"
puts in_words(82102713) == "eighty two million one hundred two thousand seven hundred thirteen"

答案 1 :(得分:11)

你认为'人性化'吗?

https://github.com/radar/humanize

答案 2 :(得分:6)

您还可以使用to_words gem。

这个宝石将整数转换为单词。

e.g。

1.to_words # one ,

100.to_words # one hundred ,

101.to_words # one hundred and one

它也会转换负数。

答案 3 :(得分:2)

简单回答使用humanize gem,您将获得所需的输出

require 'humanize'

1.humanize       #=> 'one'
345.humanize     #=> 'three hundred and forty-five'
1723323.humanize #=> 'one million, seven hundred and twenty-three thousand, three hundred and twenty-three'

如果您在rails中使用此功能,则可以直接使用此

答案 4 :(得分:1)

我可以看到您正在寻找的内容,您可能希望查看此StackOverflow帖子:Number to English Word Conversion Rails

总结如下:

  

不,你必须自己写一个功能。最接近的是什么   你想要的是number_to_human,但是不能将1转换为One。

     

以下是一些可能有用的网址:

     

http://codesnippets.joyent.com/posts/show/447   http://raveendran.wordpress.com/2009/05/29/ruby-convert-number-to-english-word/   http://deveiate.org/projects/Linguistics/

答案 5 :(得分:0)

我不太确定,如果这适合你。方法可以像这样调用。

n2w(33123) {|i| puts i unless i.to_s.empty?}

这是方法(我没有完全测试过。我认为它的工作量高达百万。代码很难看,有很多重新分解的空间。)

def n2w(n)
  words_hash = {0=>"zero",1=>"one",2=>"two",3=>"three",4=>"four",5=>"five",6=>"six",7=>"seven",8=>"eight",9=>"nine",
                    10=>"ten",11=>"eleven",12=>"twelve",13=>"thirteen",14=>"fourteen",15=>"fifteen",16=>"sixteen",
                     17=>"seventeen", 18=>"eighteen",19=>"nineteen",
                    20=>"twenty",30=>"thirty",40=>"forty",50=>"fifty",60=>"sixty",70=>"seventy",80=>"eighty",90=>"ninety"}
  scale = {3=>"hundred",4 =>"thousand",6=>"million",9=>"billion"}

  if words_hash.has_key?n
    yield words_hash[n] 
  else
    ns = n.to_s.split(//)
      while ns.size > 0      
        if ns.size == 2
            yield("and")
            yield words_hash[(ns.join.to_i) - (ns.join.to_i)%10]            
            ns.shift
        end
        if ns.size > 4
          yield(words_hash[(ns[0,2].join.to_i) - (ns[0,2].join.to_i) % 10])
        else
          yield(words_hash[ns[0].to_i]) 
        end
        yield(scale[ns.size])
        ns.shift
      end
    end
end

答案 6 :(得分:0)

问这个问题已经有一段时间了。 Rails 现在为此内置了一些东西。 https://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html

number_to_human(1234567)                                      # => "1.23 Million"
number_to_human(1234567890)                                   # => "1.23 Billion"
number_to_human(1234567890123)                                # => "1.23 Trillion"
number_to_human(1234567890123456)                             # => "1.23 Quadrillion"
number_to_human(1234567890123456789)                          # => "1230 Quadrillion"

答案 7 :(得分:-1)

以下是我选择解决问题的方法,使用几种较小的方法来处理解决方案。希望这有帮助!

module WordsModule

  def in_words

    if self == 0
      return "zero"
    elsif self > 999_999_999_999
      return trillions(self)
    elsif self > 999_999_999
      return billions(self)
    elsif self > 999_999
      return millions(self)
    elsif self > 999
      return thousands(self)
    elsif self > 99
      return hundreds(self)
    elsif self > 9
      return "#{tens(self)}"
    else
      return "#{single(self)}"
    end

  end

private

  def trillions(number)
    if number.between?(100_000_000_000_000, 999_999_999_999_999)
      if number % 1_000_000_000_000 == 0
        "#{hundreds(number/1_000_000_000_000)} trillion"
      else
        "#{hundreds(number/1_000_000_000_000)} trillion #{billions(number%1_000_000_000_000)}"
      end
    elsif number.between?(10_000_000_000_000, 99_999_999_999_999)
      if number % 1_000_000_000_000 == 0
        "#{tens(number/1_000_000_000_000)} trillion"
      else
        "#{tens(number/1_000_000_000_000)} trillion #{billions(number%1_000_000_000_000)}"
      end
    elsif number.between?(1_000_000_000_000, 9_999_999_999_999)
      if number % 1_000_000_000_000 == 0
        "#{single(number/1_000_000_000_000)} trillion"
      else
        "#{single(number/1_000_000_000_000)} trillion #{billions(number%1_000_000_000_000)}"
      end
    else
      millions(number)
    end
  end


  def billions(number)
    if number.between?(100_000_000_000, 999_999_999_999)
      if number % 1_000_000_000 == 0
        "#{hundreds(number/1_000_000_000)} billion"
      else
        "#{hundreds(number/1_000_000_000)} billion #{millions(number%1_000_000_000)}"
      end
    elsif number.between?(10_000_000_000, 99_999_999_999)
      if number % 1_000_000_000 == 0
        "#{tens(number/1_000_000_000)} billion"
      else
        "#{tens(number/1_000_000_000)} billion #{millions(number%1_000_000_000)}"
      end
    elsif number.between?(1_000_000_000, 9_999_999_999)
      if number % 1_000_000_000 == 0
        "#{single(number/1_000_000_000)} billion"
      else
        "#{single(number/1_000_000_000)} billion #{millions(number%1_000_000_000)}"
      end
    else
      millions(number)
    end
  end


  def millions(number)
    if number.between?(100_000_000, 999_999_999)
      if number % 1_000_000 == 0
        "#{hundreds(number/1_000_000)} million"
      else
        "#{hundreds(number/1_000_000)} million #{thousands(number%1_000_000)}"
      end
    elsif number.between?(10_000_000, 99_999_999)
      if number % 1_000_000 == 0
        "#{tens(number/1_000_000)} million"
      else
        "#{tens(number/1_000_000)} million #{thousands(number%1_000_000)}"
      end
    elsif number.between?(1_000_000, 9_999_999)
      if number % 1_000_000 == 0
        "#{single(number/1_000_000)} million"
      else
        "#{single(number/1_000_000)} million #{thousands(number%1_000_000)}"
      end
    else
      thousands(number)
    end
  end


  def thousands(number)
    if number.between?(100_000, 999_999)
      if number % 1000 == 0
        "#{hundreds(number/1000)} thousand"
      else
        "#{hundreds(number/1000)} thousand #{hundreds(number%1000)}"
      end
    elsif number.between?(10_000, 99_999)
      if number % 1000 == 0
        "#{tens(number/1000)} thousand"
      else
        "#{tens(number/1000)} thousand #{hundreds(number%1000)}"
      end
    elsif number.between?(1_000, 9_999)
      if number % 1000 == 0
        "#{single(number/1000)} thousand"
      else
        "#{single(number/1000)} thousand #{hundreds(number%1000)}"
      end
    else
      hundreds(number)
    end
  end


  def hundreds(number)
    if number % 100 == 0
      "#{single(number/100)} hundred"
    elsif number.between?(101, 999)
      "#{single(number/100)} hundred #{tens(number%100)}"
    else
      tens(number)
    end
  end


  def tens(number)
    teens = {
      11 => "eleven",
      12 => "twelve",
      13 => "thirteen",
      14 => "fourteen",
      15 => "fifteen",
      16 => "sixteen",
      17 => "seventeen",
      18 => "eighteen",
      19 => "nineteen"
    }

    tens = {
      1 => "ten",
      2 => "twenty",
      3 => "thirty",
      4 => "forty",
      5 => "fifty",
      6 => "sixty",
      7 => "seventy",
      8 => "eighty",
      9 => "ninety"
    }

    if number.between?(11, 19)
      teens[number]
    elsif number % 10 == 0
      tens[number/10]
    elsif number.between?(21, 99)
      "#{tens[number/10]} #{single(number%10)}"
    else
      single(number)
    end
  end


  def single(number)
    single_digit_hash = {
      1 => "one",
      2 => "two",
      3 => "three",
      4 => "four",
      5 => "five",
      6 => "six",
      7 => "seven",
      8 => "eight",
      9 => "nine"
    }

    single_digit_hash[number]
  end

end


class Integer
  include WordsModule
end