Never been to TextSnippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world (or not, you can keep them private!)

Convert numbers to words (See related posts)

Ugly code. But it works. If you have something better, then post it.

This code is probably (definitely :-) buggy, so if you want to get real work done, just use the Linguistics gem instead.

class Number
  
  def self.to_words(number)
    Number.new.to_s(number)
  end
  
  def self.commify(number)
    (s=number.to_s;x=s.length;s).rjust(x+(3-(x%3))).gsub(/(\d)(?=\d{3}+(\.\d*)?$)/,'\1,')
  end
    
  def initialize
    @unit = %w[zero one two three four five six seven eight nine]
    @teen = %w[ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen]
    @tens = %w[zero ten twenty thirty fourty fifty sixty seventy eighty ninety]
    @qtys = %w[hundred thousand million billion trillion quadrillion quintillion]
    @zero = ["zero"]
    @hundred = "hundred"
    @sepr = "and"
  end
    
  def to_s(number)
    out = quantify(number).flatten
    for x in 0 .. out.length - 1
      out[x] = nil if out[x] == @sepr && out[x+1] == @sepr
    end
    out.compact!
    out = @zero if out.length == 1 && out[0] == @sepr
    out.pop while out.last == @sepr
    out.shift while out.first == @sepr    
    out.join(' ').gsub(/ ,/,',')
  end
        
  private 
  
  def padded_groups(v)
    out = []
    padded = (s=v.to_s;x=s.length;s).rjust(x+(3-(x%3))).gsub(//,'0')
    padded.scan(/.{3}/)
  end
  
  def wordify(v)
    out = []
    zero = '0'[0]
    h, t, u = v[0] - zero, v[1] - zero, v[2] - zero
    if h != 0
      out << @unit[h]
      out << @hundred
    end
    out << @sepr if h != 0 && (t != 0 || u != 0)
    out << @sepr if h == 0 && t == 0 && u != 0
    if t == 1
      out << @teen[u]
    else
      out << @tens[t] if t != 0
      out << @unit[u] if u != 0
    end
    return out
  end
  
  def quantify(v)
    v = padded_groups(v).reverse
    pos = v.length - 1
    out = []
    while pos >= 0
      word = wordify(v[pos])
      if word[0] != nil
        out << word
        out << @qtys[pos] if pos != 0                
      else
        out << @sepr
      end
      pos -= 1
    end
    return out
  end

end

# for number in [
#     0, 
#     1, 
#     3, 
#     11, 
#     100,
#     1000, 
#     1001, 
#     1100, 
#     1101, 
#     1_000_001, 
#     8_000_000_000, 
#     8_000_000_001, 
#     4_567_890_923, 
#     6_804_567_890_903, 
#     5_006_804_567_890_903
#   ]
#   print "#{Number.commify(number)}: #{Number.to_words(number)}\n"
# end

Comments on this post

kebab_king posts on May 10, 2006 at 04:13
Attention good sir:
Your'e code is not working at all. Did you even "test" this? I think not and by the Power of The God I am getting correct on this Time!! What fuck thing is this? My Friend, I hoping very seriously for you to fuck your Mohther. Please, kindly, allowing me to prove one example:
EAT <%= Number.to_words(101) %> FUCK

output: EAT ten thousand and one FUCK

EAT <%= Number.to_words(1123) %> FUCK

EAT ten thousand two hundred and three FUCK

EAT <%= Number.to_words(1) %> FUCK

EAT zero FUCK

Now do you see how all of the things are always never working??

Your friend.
segy posts on May 18, 2006 at 23:08
Check out the linguistics gem. http://www.deveiate.org/code/Linguistics.shtml
incognito posts on Aug 23, 2006 at 14:49
@kebab_king

Since you spent no time at all writing this, and I am not being paid by you for this, what's your problem? Do you really have to insult my mother?

If you have something better, then post it, as I said. If you found a bug, fix it.

The code is not the best and I probably posted an older version and forgot to update it when I moved on.

Like segy suggests, you may want to try the linguistics gem. Good luck with that.

You need to create an account or log in to post comments to this site.


Related Posts