in reply to Re: Seeking a module to convert numbers to words
in thread Seeking a module to convert numbers to words

Thanks Perlbotics. This has less functionality than Lingua::EN::Numbers but handles larger numbers. Mind you, if I ever saw something like three vigintillion written down, I'd probably need to look it up. :-)

So I did look it up: vigintillion = 1063

Not too sure how to work that into casual conversation without getting my face slapped, though.

Update: The only number I remember from when I studied molarity is twenty-two point four which is obviously substantially smaller then six vigintillion. :-)

(I remember it from: 1 mole of a gas at stp has a volume of 22.4l)

Update 2: s{1023}{1063} - curious typo as my source had the correct value.

-- Ken

  • Comment on Re^2: Seeking a module to convert numbers to words

Replies are listed 'Best First'.
Re^3: Seeking a module to convert numbers to words
by pvaldes (Chaplain) on Aug 20, 2011 at 17:47 UTC
    ... or alternatively filter all numbers first in your document, add some if and else rules here and there and create a %hash with this, it depends on what do you need exactly and could be more eficient if you only need to store what you have

      Update: My apologies pvaldes. This was not poorly received! I believe I have confused reception to a different post of yours. Probably need new glasses or something. Again, sorry. My original response follows:

      pvaldes, thanks for taking the time to reply. As I'm sure you're aware by now, your response has not been well received. Let's see if we can garner something positive from the exercise.

      In my original prototype code, I had something which is perhaps on par with what you're suggesting. Rather than digging out old versions, this gives an idea of what it may have looked like:

      # TODO - prototype code only! my @num2word = qw{zero one two ... twenty}; ... say q{I have }, $num2word[$apple_count], q{ apples.};

      Moving out of the prototype phase, this code obviously needed to be more robust. I searched around for an existing module without success and, having decided this would be an interesting exercise, came up with the following proof-of-concept:

      After ironing out bugs (mostly to do with output format), I put the non-test parts of this code into a module: Util::Number. Having added to @fixed_test_data as I tested, I have values for regression testing (which is still to do as well as POD).

      I was surprised that I hadn't been able to find any code like this. I decided to ask here and, if no one had any better ideas, look at putting this functionality on CPAN. You know the rest from this thread.

      Here's a quick comparison of the modules mentioned:

      $ perl -Mstrict -wE 'use Number::Spell; say spell_number(100010001001) +' one hundred billion ten million one thousand one $ perl -Mstrict -wE 'use Lingua::EN::Numbers qw{num2en}; say num2en(10 +0010001001)' one hundred billion, ten million, one thousand and, one $ perl -Mstrict -wE 'use Util::Number; say conv_num_to_text(1000100010 +01)' one hundred billion, ten million, one thousand and one

      In closing, providing something substantial will generally be well received whereas "... add some if and else rules here and there ..." will not. As you can see, while I have thrown a few ifs and elses around, there was nothing in your post that suggested how I should do this.

      I recommend you take a look at To Answer, Or Not To Answer.....

      P.S. I haven't downvoted your node: I reckon you've got enough bad press already. :-)

      -- Ken

        In dirty and blooding pseudocode 1- Simplify the idea. You don need all of this

        my @units my @teens my @tens

        You only need this:

        my %number = ( 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 => sixtee +n, 17 => seventeen, 18 => eighteen, 19 => nineteen, 20 => twenty, 30 +=> thirty, 40 => forty, 50 => fifty, 60 => sixty, 70 => seventy, 80 = +> eighty, 90 => ninety);
        No, you don't need a bigger hash, you could make it bigger but this is not necessary probably.

        2 - pick up the whole number, by your preferred method, maybe a regex \d{1,}. Store the number in a variable

        3 -Proceed to parse the number

        if $number is a key in the hash, print its value, end of the history else you need to reduce the problem while $number is not undef extract the last number of the chain with pop if the popped number = 0 forget this number else my $units = this number pop again if you have a zero: good bye zero! else my $teen = this number *10 pop again if you have a zero: good bye zero! else my $hundred = this number my $thereis_a_hundred = true; ... etc, etc ... pop again ... oups, nothing left to pop, we obtain undef and ex +it the loop, my $googolplex = ''; # this variable was not reached, its value +is still the null string, so if you print it nothing occurs } ## print all variables you have collected in reversed position and a +dd some extra strings ## first whe prepare the extra chains, this could be done before also if ($there_is_hundred is true){my $hundred_str = "hundred and "} else {$hundred_str = ''}; if ($there_is_thousand is true){my $thousand_string = " thousand, "} else {$thousand_string = ''}; # ... etc # we finish print ....... %number[$thousand] $thousand_string %number[$hundred] + $hundred_str %number[$teen], %number[$unit]; # and we close all with the required "}"

        This is more or less all that you need, of course you can refine the idea a lot: you can simplify the idea behind there_is_hundred / hundred_str and do all in one steep with one variable, you should also do something with floating numbers, and you should aware that billion could be a very different creature in Europe and in USA and, and, and...

        But in any case, the idea behind all is very simple. Treat the number as a chain, pop the numbers one by one until you have undef, eval the number each time, fill as many variables as digits you have and print all together at the end, including the invisible null variables