jhon
jhon

Reputation:

Convert decimal number to words

The following PHP code converts a number to written words. This works fine for an integer like 5250, however, when given a number with a decimal, it does not parse the number correctly.

450 would output "four hundred fifty". However, 450.5 would output "four thousand five hundred five." It should be four hundred fifty point five.

I have searched the web, but I am unable to come up with a solution. Can anybody suggest a correction?

<?php
    function inr($number){
        //A function to convert numbers into words.
        $words = array(
        '0'=> '' ,'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' => 'fouteen','15' => 'fifteen',
        '16' => 'sixteen','17' => 'seventeen','18' => 'eighteen','19' => 'nineteen','20' => 'twenty',
        '30' => 'thirty','40' => 'fourty','50' => 'fifty','60' => 'sixty','70' => 'seventy',
        '80' => 'eighty','90' => 'ninty');

        //First find the length of the number
        $number_length = strlen($number);
        //Initialize an empty array
        $number_array = array(0,0,0,0,0,0,0,0,0);        
        $received_number_array = array();

        //Store all received numbers into an array
        for($i=0;$i<$number_length;$i++){    $received_number_array[$i] = substr($number,$i,1);    }

        //Populate the empty array with the numbers received - most critical operation
        for($i=9-$number_length,$j=0;$i<9;$i++,$j++){ $number_array[$i] = $received_number_array[$j]; }
        $number_to_words_string = "";        
        //Finding out whether it is teen ? and then multiplying by 10, example 17 is seventeen, so if 1 is preceeded with 7 multiply 1 by 10 and add 7 to it.
        for($i=0,$j=1;$i<9;$i++,$j++){
            if($i==0 || $i==2 || $i==4 || $i==7){
                if($number_array[$i]=="1"){
                    $number_array[$j] = 10+$number_array[$j];
                    $number_array[$i] = 0;
                }        
            }
        }

        $value = "";
        for($i=0;$i<9;$i++){
            if($i==0 || $i==2 || $i==4 || $i==7){    $value = $number_array[$i]*10; }
            else{ $value = $number_array[$i];    }            
            if($value!=0){ $number_to_words_string.= $words["$value"]." "; }
            if($i==1 && $value!=0){    $number_to_words_string.= "Crores "; }
            if($i==3 && $value!=0){    $number_to_words_string.= "Lakhs ";    }
            if($i==5 && $value!=0){    $number_to_words_string.= "Thousand "; }
            if($i==6 && $value!=0){    $number_to_words_string.= "Hundred "; }
        }
        if($number_length>9){ $number_to_words_string = "Sorry This does not support more than 99 Crores"; }
        return ucwords(strtolower("Rupees ".$number_to_words_string)." Only.");

    }

$my_fig=inr(450.5);
    echo $my_fig;

?>

Upvotes: 0

Views: 1766

Answers (3)

Logan Wayne
Logan Wayne

Reputation: 5991

Determine first the whole number and the number after decimal point, use $number=explode(".",$number); to separate the two numbers into an array.

$number[0] would be your whole number and $number[1] would be your number after the decimal point.

function inr($number[0]){
/* Your function for the whole number */
}

function inr2($number[1]){
/* Your function for the number after the decimal point */
}

Upvotes: 0

Luke Cordingley
Luke Cordingley

Reputation: 685

Here is a working solution. It might not work completely with what your are trying to do but it should be a good start. The key is to re-use your work through a single recursive call. If you call your function again for the numbers AFTER the decimal place you can then combine the results:

function inr($number, $doOtherWords = true){
    //A function to convert numbers into words.
    $words = array(
    '0'=> '' ,'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' => 'fouteen','15' => 'fifteen',
    '16' => 'sixteen','17' => 'seventeen','18' => 'eighteen','19' => 'nineteen','20' => 'twenty',
    '30' => 'thirty','40' => 'fourty','50' => 'fifty','60' => 'sixty','70' => 'seventy',
    '80' => 'eighty','90' => 'ninty');

    //First find the length of the number
    $number_length = strlen($number);
    //Initialize an empty array
    $number_array = array(0,0,0,0,0,0,0,0,0);        
    $received_number_array = array();

    // Save off if we have a decimal in a variable. Assume we don't
    $hasDecimal = false;
    $numberAfterDecimal = '';
    //Store all received numbers into an array
    //ONLY do this until we find a decimal
    for($i=0;$i<$number_length;$i++) { 
        $character = substr($number,$i,1);    
        if ($character == '.') {
            $hasDecimal = true;
            $numberAfterDecimal = substr($number, $i+1);
            $received_number_array[$i] = 0;
        } elseif ($hasDecimal) {
            $received_number_array[$i] = 0;
        } else {
            $received_number_array[$i] = $character;
        }
    }


    //Populate the empty array with the numbers received - most critical operation
    for($i=9-$number_length,$j=0;$i<9;$i++,$j++){ $number_array[$i] = $received_number_array[$j]; }
    $number_to_words_string = "";        
    //Finding out whether it is teen ? and then multiplying by 10, example 17 is seventeen, so if 1 is preceeded with 7 multiply 1 by 10 and add 7 to it.
    for($i=0,$j=1;$i<9;$i++,$j++){
        if($i==0 || $i==2 || $i==4 || $i==7){
            if($number_array[$i]=="1"){
                $number_array[$j] = 10+$number_array[$j];
                $number_array[$i] = 0;
            }        
        }
    }
    $value = "";
    for($i=0;$i<9;$i++){
        if($i==0 || $i==2 || $i==4 || $i==7){
            $value = $number_array[$i]*10; 
        } else{ 
            $value = $number_array[$i];
        }            

        if($value!=0){ 
            $number_to_words_string.= $words["$value"]." "; 
        }

        if ($doOtherWords) {
            if($i==1 && $value!=0){    $number_to_words_string.= "Crores "; }
            if($i==3 && $value!=0){    $number_to_words_string.= "Lakhs ";    }
            if($i==5 && $value!=0){    $number_to_words_string.= "Thousand "; }
            if($i==6 && $value!=0){    $number_to_words_string.= "Hundred "; }
        }
    }

    // At this point you have the solution for everything BEFORE the decimal
    // Now handle the decimal through recursion if in fact we have one
    if ($hasDecimal) {
        $number_to_words_string .= 'point ' . inr($numberAfterDecimal, false);
    }
    if($number_length>9){ $number_to_words_string = "Sorry This does not support more than 99 Crores"; }
    if ($doOtherWords) {
        return ucwords(strtolower("Rupees ".$number_to_words_string)."Only.");
    }
    // Don't add the other words on the recursive call
    return ucwords(strtolower($number_to_words_string));
}

$my_fig=inr(450.56);
echo $my_fig;

Upvotes: 0

elixenide
elixenide

Reputation: 44833

The code in the question makes no effort to split the number on the decimal point; it just looks at all digits in the string. So, of course it doesn't work. To make it work correctly:

  • Process the part before the decimal point using the routine above.
  • If there is a decimal point:
    • add "point"
    • add one word per digit after the decimal point, so .45 becomes point four five, for example.

Upvotes: 1

Related Questions