#!/usr/bin/perl -W # # dectoeng.pl: translate decimal numbers into English # i.e. 10 -> ten, 183 -> one hundred eighty-three # # John Chesley # October 26-28, 2005 # use strict; # # Numbers we'll need to know # my @numbers = ("", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"); my @teens = ("ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"); my @prefixes = ("", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty","ninety"); # Just add the right names to this array to make the program support higher numbers. The first two empty ones are placeholders my @magnitudes = ("", "", "thousand", "million", "billion", "trillion", "quadrillion", "quintillion", "sextillion", "septillion", "octillion", "nonillion", "decillion", "undecillion", "duodecillion", "tredecillion", "quattuordecillion", "quindecillion", "sexdecillion", "septendecillion", "octodecillion", "novemdecillion", "vigintillion", "unvigintillion", "duovigintillion", "trevigintillion"); if (!($ARGV[0])) { print "Usage: dectoeng.pl [-c] number\nTranslates number into English suitable for writing a check with. \nUse -c to print a string suitable for placement on a check.\n"; exit 0; } my $number = shift @ARGV; my $check = 0; if ($number eq "-c") { $check = 1; $number = shift @ARGV; } else { $check = 0; } print split /./, $number; my $decimals = '00'; unless ((index $number, '.') == -1) { my @splitnum = split //, $number . '00'; # the . '00' fixes an error if the number has fewer than 2 decimal places my $index = index $number, '.'; $number = join '', @splitnum[0..$index-1]; $decimals = join '', @splitnum[$index+1..$index+2]; } if ($number =~ /\D/ or $decimals =~ /\D/) { print "Hey! Numbers only, jerk. I can't go from english to decimal. Sorry!.\n"; exit 1; } my $numdigits = index $number, '.'; if ($numdigits < 0) { $numdigits = length $number; } my @digits = split //, $number; my $chunked = ""; my $i = 0; foreach my $digit (reverse @digits) { if (($i % 3) == 0 and ($i != 0)) { $chunked .= ','; } $chunked .= $digit; $i++; } $chunked = reverse split //, $chunked; my @chunks = split /,/, $chunked; my $numchunks = scalar @chunks; unless ($numchunks < scalar @magnitudes) { print "Sorry, I don't do numbers bigger than in the $magnitudes[-1]'s.\n"; exit 0; } my $teen = 0; my $translated = ""; foreach my $chunk (@chunks) { my $i = 0; my @chunkdigits = split //, $chunk; for ($i=0; $i < length $chunk; $i++) { my $digit = $chunkdigits[$i]; my $nextdigit = 0; unless (!$chunkdigits[$i+1]) { $nextdigit = $chunkdigits[$i+1]; } if ($teen) { # catch and reset the teen flag $translated .= $teens[$digit] . " "; $teen = 0; } elsif ($digit==0) { $translated .= " "; } elsif ($i==0 and length $chunk==3) { $translated .= $numbers[$digit] . " hundred "; } elsif (($i==1 and length $chunk==3) or ($i==0 and length $chunk==2)) { if ($digit == 1) { $teen = 1 # Oh-no - a dreaded 'teen'! Set a flag for next iteration } else { $translated .= $prefixes[$digit]; unless ($nextdigit == 0) { $translated .= "-"; } } } else { $translated .= $numbers[$digit] . " "; } } if ($chunk==000) { --$numchunks; } else { $translated .= $magnitudes[$numchunks--] . " "; } } $translated .= "and $decimals/100" if ($check); $translated .= "\n"; $translated =~ s/[ ]{2,}/ /g; # Replace multiple spaces with a single one print $translated;