Using Ruby convert numbers to words?

前端 未结 8 1365
广开言路
广开言路 2020-12-09 19:30

How to convert numbers to words in 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 integ

相关标签:
8条回答
  • 2020-12-09 19:54

    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
    
    0 讨论(0)
  • 2020-12-09 19:57

    I can see what you're looking for, and you may wish to check out this StackOverflow post: 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/447 http://raveendran.wordpress.com/2009/05/29/ruby-convert-number-to-english-word/ http://deveiate.org/projects/Linguistics/

    0 讨论(0)
  • 2020-12-09 20:04

    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
    
    0 讨论(0)
  • 2020-12-09 20:05

    Have you consider 'humanize' ?

    https://github.com/radar/humanize

    0 讨论(0)
  • 2020-12-09 20:08

    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"
    
    0 讨论(0)
  • 2020-12-09 20:10

    Simple answer use humanize gem and you will get desired output

    Install it directly

    gem install humanize
    

    Or add it to your 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

    NOTE: As mentioned by sren in the comments below. The humanize method provided by ActiveSupport is different than the gem humanize

    0 讨论(0)
提交回复
热议问题