Forum: Ruby on Rails format numbers as words

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
2b404bb55d9b5dc78841795c4b731771?d=identicon&s=25 Damien Timewell (idlefingers)
on 2006-04-30 03:24
Does anyone know if there is a function available which can format any
entered number as words?

eg: '1234' would be 'One Thousand Two Hundred and Thirty Four'

In the past, I would have said this is a tall order, but from what I've
seen with playing with rails for a short time, I don't know what to
expect. :)

Thanks for any help,
Damien
6dab365a82517fb694650a57ee88e4a4?d=identicon&s=25 joey__ (Guest)
on 2006-04-30 11:39
Damien Timewell wrote:
> Does anyone know if there is a function available which can format any
> entered number as words?
>
> eg: '1234' would be 'One Thousand Two Hundred and Thirty Four'
>
> In the past, I would have said this is a tall order, but from what I've
> seen with playing with rails for a short time, I don't know what to
> expect. :)
>
> Thanks for any help,
> Damien
http://www.rubyquiz.com/quiz25.html

j`ey
http://www.eachmapinject.com
2b404bb55d9b5dc78841795c4b731771?d=identicon&s=25 Damien Timewell (idlefingers)
on 2006-05-01 02:29
joey__ wrote:
> Damien Timewell wrote:
>> Does anyone know if there is a function available which can format any
>> entered number as words?
>>
>> eg: '1234' would be 'One Thousand Two Hundred and Thirty Four'
>>
>> In the past, I would have said this is a tall order, but from what I've
>> seen with playing with rails for a short time, I don't know what to
>> expect. :)
>>
>> Thanks for any help,
>> Damien
> http://www.rubyquiz.com/quiz25.html
>
> j`ey
> http://www.eachmapinject.com

Thanks, that looks perfect, but i'm really confused as to how I
implement it.. it doesnt explain on that page how to actually use it??

Sorry, i'm a real noob with rails.
6dab365a82517fb694650a57ee88e4a4?d=identicon&s=25 j`ey (Guest)
on 2006-05-01 11:29
Damien Timewell wrote:
> joey__ wrote:
>> Damien Timewell wrote:
>>> Does anyone know if there is a function available which can format any
>>> entered number as words?
>>>
>>> eg: '1234' would be 'One Thousand Two Hundred and Thirty Four'
>>>
>>> In the past, I would have said this is a tall order, but from what I've
>>> seen with playing with rails for a short time, I don't know what to
>>> expect. :)
>>>
>>> Thanks for any help,
>>> Damien
>> http://www.rubyquiz.com/quiz25.html
>>
>> j`ey
>> http://www.eachmapinject.com
>
> Thanks, that looks perfect, but i'm really confused as to how I
> implement it.. it doesnt explain on that page how to actually use it??
>
> Sorry, i'm a real noob with rails.

Add the code from:
http://www.ruby-talk.org/cgi-bin/scat.rb/ruby/ruby...

Into a english_numbers.rb in the lib/ folder. Then do require
'lib/english_numbers.rb'


Then do EnglishNumerals.to_English(number)

j`ey
http://eachmapinject.com
2b404bb55d9b5dc78841795c4b731771?d=identicon&s=25 Damien Timewell (idlefingers)
on 2006-05-01 13:07
>>
>> Thanks, that looks perfect, but i'm really confused as to how I
>> implement it.. it doesnt explain on that page how to actually use it??
>>
>> Sorry, i'm a real noob with rails.
>
> Add the code from:
> http://www.ruby-talk.org/cgi-bin/scat.rb/ruby/ruby...
>
> Into a english_numbers.rb in the lib/ folder. Then do require
> 'lib/english_numbers.rb'
>
>
> Then do EnglishNumerals.to_English(number)
>
> j`ey
> http://eachmapinject.com

Thanks for the help, but i'm still quite confused.

I did as you said, made the file in lib but I wasn't too sure where to
put the require so I've tried everything - in the model, helper and
controller. Wherever I put it, it returned an error, but when it was in
the controller, rather than saying it couldn't find the file or
something to that effect, it said "wrong number of arguments (0 for 1)"
4ba4bb954bcfec077d9708b540558926?d=identicon&s=25 Guido Sohne (Guest)
on 2006-05-03 18:56
(Received via mailing list)
Place the code into a file called number.rb ... you can put it in your
models directory for example.

If it is in your models directory, then you don't even need to require
'number' - all you do is make a call to Number.to_words and pass the
amount as a parameter ...

insight$ ls
number.rb
insight$ irb
irb(main):001:0> require 'number'
=> true
irb(main):002:0> Number.to_words 345678
=> "three hundred and fourty five thousand six hundred and seventy
eight"
irb(main):003:0> exit
insight$
4ba4bb954bcfec077d9708b540558926?d=identicon&s=25 Guido Sohne (Guest)
on 2006-05-03 19:10
(Received via mailing list)
Does this do the trick? You can uncomment the commented lines at the
end and run the script to see if it works. Improvements and better
ways to do this are appreciated ...

-- G.

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
      out[x] = nil if out[x] == "," && out[x+1] == ","
    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
    cur = pos = v.length - 1
    out = []
    while pos >= 0
      if v[pos] == ','
        out << ','
        next
      end
      word = wordify(v[pos])
      if word[0] != nil
        out << word
        out << @qtys[cur] if cur != 0
      else
        out << @sepr
      end
      cur -= 1
      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
2b404bb55d9b5dc78841795c4b731771?d=identicon&s=25 Damien Timewell (idlefingers)
on 2006-05-03 19:19
thanks, Guido Sohne, that did the trick.

when I tried it with the previous code from j`ey, it killed my server
and I had to reboot, but with that new script, it's perfect. thanks
again.
A049c3597983fdaaa2af2b0010c49abc?d=identicon&s=25 Tim Perrett (timperrett)
on 2006-09-22 12:41
Just the job!!! thats a great class

Cheers

Tim
This topic is locked and can not be replied to.