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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19445003/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 22:53:10  来源:igfitidea点击:

Using Ruby convert numbers to words?

ruby-on-railsrubynumbers

提问by hken27

How to convert numbers to words in ruby?

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

I know there is a gem somewhere. Trying to implement it without a gem. I just need the numbers to words in English for integers. Found this but it is very messy. If you have any idea on how to implement a cleaner easier to read solution please share.

我知道某处有一颗宝石。试图在没有 gem 的情况下实现它。我只需要数字到英文单词的整数。找到了这个,但是很乱。如果您对如何实现更简洁易读的解决方案有任何想法,请分享。

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

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

Here is what I have been working on. But having some problem implementing the scales. The code is still a mess. I hope to make it more readable when it functions properly.

这是我一直在研究的内容。但是在实施秤时遇到了一些问题。代码还是一团糟。我希望在它正常运行时使其更具可读性。

   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)

回答by NoNonsense

My take on this

我对此的看法

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"

回答by rhernando

Have you consider 'humanize' ?

你考虑过“人性化”吗?

https://github.com/radar/humanize

https://github.com/radar/humanize

回答by taimur akhtar

You can also use the to_wordsgem.

您还可以使用to_wordsgem。

This Gem converts integers into words.

这个 Gem 将整数转换为单词。

e.g.

例如

1.to_words # one ,

100.to_words # one hundred ,

101.to_words # one hundred and one

It also converts negative numbers.

它还转换负数。

回答by Deepak Mahakale

Simple answer use humanizegem and you will get desired output

简单的答案使用humanizegem,您将获得所需的输出

Install it directly

直接安装

gem install humanize

Or add it to your Gemfile

或者将它添加到您的 Gemfile

gem 'humanize'

And you can use it

你可以使用它

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'

If you are using this in rails you can directly use this

如果你在 Rails 中使用它,你可以直接使用它

NOTE: As mentioned by srenin the comments below. The humanizemethod provided by ActiveSupportis different than the gem humanize

注意:正如sren在下面的评论中所提到的。提供的人性化方法ActiveSupport与 gem 不同humanize

回答by Richard Peck

I can see what you're looking for, and you may wish to check out this StackOverflow post: Number to English Word Conversion Rails

我可以看到你在找什么,你可能希望查看这篇 StackOverflow 帖子:Number to English Word Conversion Rails

Here it is in summary:

总结如下:

No, you have to write a function yourself. The closest thing to what you want is number_to_human, but that does not convert 1 to One.

Here are some URLs that may be helpful:

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

不,你必须自己写一个函数。最接近您想要的是 number_to_human,但这不会将 1 转换为 1。

以下是一些可能有用的 URL:

http://codesnippets.joyent.com/posts/show/447 http://raveendran.wordpress.com/2009/05/29/ruby-convert-number-to-english-word/ http://deveiate.org /项目/语言学/

回答by Bala

I am not quite sure, if this works for you. Method can be called like this.

我不太确定,这是否适合您。方法可以这样调用。

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

Here is the method ( I have not tested it fully. I think it works upto million. Code is ugly, there is a lot of room for re-factoring. )

这是方法(我没有完全测试它。我认为它可以达到百万。代码很难看,有很大的重构空间。)

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

回答by dsn raghavendra rao

def subhundred number

  ones = %w{zero one two three four five six seven eight nine
            ten eleven twelve thirteen fourteen fifteen
            sixteen seventeen eighteen nineteen}

  tens = %w{zero ten twenty thirty **forty** fifty sixty seventy eighty ninety}

  subhundred = number % 100

  return [ones[subhundred]] if subhundred < 20

  return [tens[subhundred / 10]] if subhundred % 10 == 0

  return [tens[subhundred / 10], ones[subhundred % 10]]

end




def subthousand number

  hundreds = (number % 1000) / 100

  tens = number % 100

  s = []

  s = subhundred(hundreds) + ["hundred"] unless hundreds == 0

  s = s + ["and"] unless hundreds == 0 or tens == 0

  s = s + [subhundred(tens)] unless tens == 0


end




def decimals number

  return [] unless number.to_s['.']

  digits = number.to_s.split('.')[1].split('').reverse

  digits = digits.drop_while {|d| d.to_i == 0} . reverse

  digits = digits.map {|d| subhundred d.to_i} . flatten

  digits.empty? ? [] : ["and cents"] + digits

end





def words_from_numbers number

  steps = [""] + %w{thousand million billion trillion quadrillion quintillion sextillion}

  result = []

  n = number.to_i

  steps.each do |step|

    x = n % 1000

    unit = (step == "") ? [] : [step]

    result = subthousand(x) + unit  + result unless x == 0

    n = n / 1000

  end



  result = ["zero"] if result.empty?

  result = result + decimals(number)




  result.join(' ').strip

end






 def words_from_numbers(number)

    ApplicationHelper.words_from_numbers(number)

  end

回答by David McAfee

Here is how I chose to solve the problem, using several smaller methods to handle the solution. Hope this helps!

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

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