Humanize your numbers!

I’ve created a ruby script that converts numbers into their long english forms e.g. 1233 => one thousand, two hundred and thirty-three. The code is below; to use it, just put the code in a file called numeric_humanize.rb, require 'numeric_humanize' at the top of your files, and call 5466.humanize for the English form. The script converts positive and negative integers and decimal numbers, and has a range between -999,999,999,999,999,999,999,999,999,999,999,999 and +999,999,999,999,999,999,999,999,999,999,999,999 so no number should fail to convert!

I’ll be posting often from now on, so keep checking out my blog.

class Numeric
  def humanize
    num, dec = self.to_s.split('.', 2)
    output = ''
 
    if num[0..0] == '-'
      output << 'negative '
      num = num[1..-1]
    elsif num[0..0] == '+'
      output << 'positive '
      num = num[1..-1]
    end
 
    if num[0..0] == '0'
      output << 'zero'
    else
      groups = num.rjust(36, '0').scan(/d{3}/)
      groups2 = groups.map { |g| humanize_three_digit(g[0..0], g[1..1], g[2..2]) }
 
      groups2.each_with_index do |part, z|
        output << part << (z == 11 ? '' : ' ' + HUMANIZE_GROUP_TEXT[z] + (!groups2[(z + 1)..10].detect { |g| g != '' } && groups2[11] != '' && groups[11][0..0] == '0' ? ' and ' : '', ')) if part != ''
      end
 
      output.gsub!(/, $/, '')
    end
 
    output << " point " << dec.scan(/./).map { |n| HUMANIZE_ONES_TEXT[n.to_i] }.join(' ') if dec.to_i > 0
 
    return output
  end
 
  private
  HUMANIZE_GROUP_TEXT = %w(decillion nonillion octillion septillion sextillion quintrillion quadrillion trillion billion million thousand).freeze
  HUMANIZE_TENS_TEXT = %w(ten twenty thirty forty fifty sixty seventy eighty ninety).freeze
  HUMANIZE_ELEVEN2TWENTY_TEXT = %w(eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen).freeze
  HUMANIZE_ONES_TEXT = %w(zero one two three four five six seven eight nine).freeze
 
  def humanize_three_digit(dig1, dig2, dig3)
    output = ''
 
    return '' if dig1 == '0' && dig2 == '0' && dig3 == '0'
 
    if dig1 != '0'
      output << HUMANIZE_ONES_TEXT[dig1.to_i] << ' hundred'
      output << ' and ' if dig2 != '0' or dig3 != '0'
    end
 
    if dig2 != '0'
      output << humanize_two_digit(dig2, dig3)
    elsif dig3 != '0'
      output << HUMANIZE_ONES_TEXT[dig3.to_i]
    end
 
    return output
  end
 
  def humanize_two_digit(dig1, dig2)
    if dig2 == '0'
      HUMANIZE_TENS_TEXT[dig1.to_i - 1]
    elsif dig1 == '1'
      HUMANIZE_ELEVEN2TWENTY_TEXT[dig2.to_i - 1]
    else
      HUMANIZE_TENS_TEXT[dig1.to_i - 1] + '-' + HUMANIZE_ONES_TEXT[dig2.to_i]
    end
  end
end

13:29 Tue 2008-05-13 (Index)

Say something!