字符串函数
在线手册:中文 英文
PHP手册

number_format

(PHP 4, PHP 5)

number_formatFormat a number with grouped thousands

说明

string number_format ( float $number [, int $decimals = 0 ] )
string number_format ( float $number , int $decimals = 0 , string $dec_point = '.' , string $thousands_sep = ',' )

This function accepts either one, two, or four parameters (not three):

If only one parameter is given, number will be formatted without decimals, but with a comma (",") between every group of thousands.

If two parameters are given, number will be formatted with decimals decimals with a dot (".") in front, and a comma (",") between every group of thousands.

If all four parameters are given, number will be formatted with decimals decimals, dec_point instead of a dot (".") before the decimals and thousands_sep instead of a comma (",") between every group of thousands.

参数

number

The number being formatted.

decimals

Sets the number of decimal points.

dec_point

Sets the separator for the decimal point.

thousands_sep

Sets the thousands separator.

返回值

A formatted version of number.

更新日志

版本 说明
5.4.0 This function now supports multiple bytes in dec_point and thousands_sep. Only the first byte of each separator was used in older versions.

范例

Example #1 number_format() Example

For instance, French notation usually use two decimals, comma (',') as decimal separator, and space (' ') as thousand separator. This is achieved with this line :

<?php

$number 
1234.56;

// english notation (default)
$english_format_number number_format($number);
// 1,235

// French notation
$nombre_format_francais number_format($number2','' ');
// 1 234,56

$number 1234.5678;

// english notation without thousands separator
$english_format_number number_format($number2'.''');
// 1234.57

?>

参见


字符串函数
在线手册:中文 英文
PHP手册
PHP手册 - N: Format a number with grouped thousands

用户评论:

qwantastic (14-Feb-2012 03:04)

I was looking for a way to format a number to a certain number of significant digits, instead of decimal points.

This is what I came up with:

function number_significant($x, $n) {
 $x_sci = sprintf("%.".$n."e", $x);
 $x_f = rtrim(sprintf("%f", $x_sci),"0");
 if ( $x_f[strlen($x_f)-1]=="." ) {
  $x_f .= "0";
 }
 return $x_f;
}

liviu andrei (bls) (18-Nov-2011 04:10)

To prevent the rounding that occurs when next digit after last significant decimal is 5 (mentioned by several people below):

<?php
function fnumber_format($number, $decimals='', $sep1='', $sep2='') {

        if ((
$number * pow(10 , $decimals + 1) % 10 ) == 5//if next not significant digit is 5
           
$number -= pow(10 , -($decimals+1));

        return
number_format($number, $decimals, $sep1, $sep2);

}

$t=7.15;
echo
$t . " | " . number_format($t, 1, '.', ',') .  " | " . fnumber_format($t, 1, '.', ',') . "\n\n";
//result is: 7.15 | 7.2 | 7.1

$t=7.3215;
echo
$t . " | " . number_format($t, 3, '.', ',') .  " | " . fnumber_format($t, 3, '.', ',') . "\n\n";
//result is: 7.3215 | 7.322 | 7.321
} ?>

have fun!

t dot ulrich at airbus-pilots dot com (29-Aug-2011 01:48)

leading zero?s are easier to do with some small if statement

<?php
$number
= 123.3;

$number = explode(".",$number);

if(
substr($number[1],1,1) == ""){
      
$number[1] = $number[1] . "0";
}

$number = $number[0]. "." .$number[1];
?>

easy...

robmann at gmx dot li (06-May-2011 12:02)

Here a function to filter exponential notation like 6e-06. Turn it to 0,000006 for comfortable reading. Supporting various number of decimals!

<?php
function easy_number_format($number, $dec_point, $thousands_sep)
{
   
$number = rtrim(sprintf('%f', $number), "0");
    if (
fmod($nummer, 1) != 0) {                     
       
$array_int_dec = explode('.', $number);
    } else {
       
$array_int_dec= array(strlen($nummer), 0);
    }
    (
strlen($array_int_dec[1]) < 2) ? ($decimals = 2) : ($decimals = strlen($array_int_dec[1]));
    return
number_format($number, $decimals, $dec_point, $thousands_sep);
}
?>

The maximum accuracy depends on sprintf('%f', $number). In this case 6 decimals. Expand it to 10 with '%.10f'.

info at swedishboy dot se (24-Jan-2011 11:12)

There has been some suggestions around on how to keep trailing zeros. Best way is to use the example for currency provided by the php-crew in the sprintf function help section.

That is:
<?php
$money1
= 68.75;
$money2 = 54.35;
$money = $money1 + $money2;

// echo $money will output "123.1";

$formatted = sprintf("%01.2f", $money); // << this does the trick!

// echo $formatted will output "123.10"

?>

WayneH (29-Nov-2010 10:24)

When using number_format to create a string for output to a CSV file you will need to override the default thousands separator of "," with null ("") so that 1,000 becomes 1000 !!!

Ali Okan YKSEL (26-Oct-2010 10:47)

function formats numbers of datetime type,

<?php
$_GET
["zaman"]="1983-8-28 5:5:5";

function
_parseDatetimeToList($datetimeStr) { //datetime format: Y-m-d H-i-s
   
$datetimeArray=explode(" ", $datetimeStr);
   
$dateArray=explode("-",$datetimeArray[0]);
   
$year=str_pad($dateArray[0], 2, "0", STR_PAD_LEFT);
   
$month=str_pad($dateArray[1], 2, "0", STR_PAD_LEFT);
   
$day=str_pad($dateArray[2], 2, "0", STR_PAD_LEFT);
   
$timeArray=explode(":",$datetimeArray[1]);
   
$hour=str_pad($timeArray[0], 2, "0", STR_PAD_LEFT);
   
$minute=str_pad($timeArray[1], 2, "0", STR_PAD_LEFT);
   
$second=str_pad($timeArray[2], 2, "0", STR_PAD_LEFT);
    return array(
$year, $month, $day, $hour, $minute, $second);
}

list(
$year, $month, $day, $hour, $minute, $second) = _parseDatetimeToList($_GET["zaman"]);  // 1983-1-28 5:5:5
?>

Ricky *@* Mataka [com] (16-Oct-2010 07:10)

Hey Guys, dont know if this is the best way but it worked for me as i faced a problem where I had to split any large number > then 10K into into to exact split amounts.. so i wrote this this to do the trick.. hope it helps some one out there!

<?php
function divide22($num)
{
 
$valone = intval($num / 2);
 
$valtwo = $valone;
  if ((
$num % 2) > 0) $valtwo++;
  return array(
$valone, $valtwo);
}
function
split2vals($num,$split_amount)

 
$store=array();
 
$times = round(($num/$split_amount));
 
$amount= $num/$times;  
  for(
$i=0;$i<$times;$i++)
  {
    
$store[]=round($amount);
  }
  foreach(
$store as $index=>$value)
  {
    if(
$value>$split_amount)
    {
      
$get_splits=divide22($value);
      
//unset the split
      
unset($store[$index]);
      
$store[]=$get_splits[0];
      
$store[]=$get_splits[1];
    }
  }
 
$sum=array_sum($store);
 
  if(
$sum > $num){
   
$sub=$sum-$num;
     
$end=end($store);
   
array_pop($store);
   
$store[]=$end-$sub;
  }
  if(
$sum < $num){
   
$store[]=($num-$sum); 
  }
  return
$store;
}

//USAGE

$check_amount=50567.83;
echo
'Input Split = '.$check_amount.'<br><br>';
$store=split2vals($check_amount,10000);
print_r($store);
$sum=array_sum($store);
echo
'<br><br>Should Be Exact ='. $sum;
exit();
?>

Anonymous (13-Oct-2010 10:52)

Caution should be taken with large "string" values. This is due to the precision issues with converting a string to a float.

For example:

<?php
$org_num
= "255173029255255255";
echo
"<br>org: ".$org_num;
echo
"<br>".number_format($org_num);
?>

returns:
org: 255173029255255255
255,173,029,255,255,264

Here is the function that can be used instead

<?php
function numberFormat($num)
{
     return
preg_replace("/(?<=\d)(?=(\d{3})+(?!\d))/",",",$num);
}
?>

Cody G. (08-Aug-2010 10:06)

Sometimes, I'm sure, you guys are looking for a way to do the exact opposite of this function: convert a comma-filled number back to normal decimal.
Here's a quick code that popped into my head today:

<?php
 $mynumstr
= "100,000,000.75";
 
$mynum = doubleval(str_replace(",","",$mynumstr));
?>

This is especially useful when validating user input. Some people like to include comma's with their numbers.
Some also like to include the dollar-sign when entering prices. Here's a modification:

<?php
 $mynumstr
= '$100,000,000.25';
 
$arr1 = array(',','$');
 
$arr2 = array('','');
 
$mynum = doubleval(str_replace($arr1,$arr2,$mynumstr));
 
//The arrays had to be defined in a
 //  variable to shorten statement.
?>

Okay, that takes care of it, I use the PHP4 array compatibility update to remove several characters.
Don't forget to either use single-quotes or escape the dollar-sign!

~Cody G.

me dot nosp at m dot unreal4u dot com (08-Jul-2010 08:36)

Maybe it is documented, but I just missed it. However, a comment is always useful.

An array will always be converted into 1, so, if you have:

<?php
$my_array
= array(55);
echo
number_format($my_array,0,',','.');
// 1
var_dump(number_format($my_array,2,',','.'));
// string(4) "1,00"
?>

Since it took me a while to figure it out, I hope this will save somebody's time.

Greetings !!

isedc at yahoo dot com (29-Mar-2010 08:38)

Some programmers may have scripts that use the number_format function twice on a variable.  However, if a number is 4 or more digits, using the function twice with only the decimals parameter will lose part of the value that follows the thousands separator.

<?php
$var
= number_format(2234,2);
$var = number_format($var,2);
echo
$var;
# Expected Output: 2,234.00
# Actual Output: 2.00
?>

To fix, remove the thousands separator by setting the decimal point and thousands separator parameters like so:

<?php
$var
= number_format(2234,2,'.','');
$var = number_format($var,2,'.','');
echo
$var;
# Expected Output: 2234.00
# Actual Output: 2234.00
?>

If it's 3 digits or less, then it works normally with only the decimals parameter since there is no thousands separator.

<?php
$var
= number_format(123,2);
$var = number_format($var,2);
echo
$var;
# Expected Output: 123.00
# Actual Output: 123.00
?>

dipu dot ashok dot 17 at gmail dot com (28-Mar-2010 09:18)

function to convert numbers to words
indian: thousand,lakh,crore
Note: function can only convert nos upto 99 crores

<?php
 $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','100' => 'hundred &','1000' => 'thousand','100000' => 'lakh','10000000' => 'crore');
function
no_to_words($no)
{    global
$words;
    if(
$no == 0)
        return
' ';
    else {          
$novalue='';$highno=$no;$remainno=0;$value=100;$value1=1000;       
            while(
$no>=100)    {
                if((
$value <= $no) &&($no  < $value1))    {
               
$novalue=$words["$value"];
               
$highno = (int)($no/$value);
               
$remainno = $no % $value;
                break;
                }
               
$value= $value1;
               
$value1 = $value * 100;
            }       
          if(
array_key_exists("$highno",$words))
              return
$words["$highno"]." ".$novalue." ".no_to_words($remainno);
          else {
            
$unit=$highno%10;
            
$ten =(int)($highno/10)*10;            
             return
$words["$ten"]." ".$words["$unit"]." ".$novalue." ".no_to_words($remainno);
           }
    }
}
echo
no_to_words(999978987);

?>

binarte at gmail dot com (24-Dec-2009 05:10)

number_format is deficient in the sense that it is currently unable to output numbers in japanese format (grouping algarisms in tens of thousands instead of thousands).
The alternative below will work just like number_format, but the added $group parameter allows to change how many algarisms per group the output will have.

<?php

function numberFormat  ($number  , $decimals = 2 , $dec_point = '.' , $sep = ',', $group=3   ){
   
$num = sprintf("%0.{$decimals}f",$number);   
   
$num = explode('.',$num);
    while (
strlen($num[0]) % $group) $num[0]= ' '.$num[0];
   
$num[0] = str_split($num[0],$group);
   
$num[0] = join($sep[0],$num[0]);
   
$num[0] = trim($num[0]);
   
$num = join($dec_point[0],$num);
   
    return
$num;
}

echo
numberformat(123456789,0,'.',' ',4); // 1 2345 6789

?>

Horvath, Sandor [HU] (05-Oct-2009 09:19)

Because I had a lot of problems with number_format, here is a working, simple and small replacement:

<?php
function FormatNumber($number, $decimals = 0, $thousand_separator = '&nbsp;', $decimal_point = '.')
{
 
$tmp1 = round((float) $number, $decimals);

  while ((
$tmp2 = preg_replace('/(\d+)(\d\d\d)/', '\1 \2', $tmp1)) != $tmp1)
   
$tmp1 = $tmp2;

  return
strtr($tmp1, array(' ' => $thousand_separator, '.' => $decimal_point));
}

echo
FormatNumber(-913578.1415, 2, '.', ',') . "\n";
?>

Will Shaver (24-Aug-2009 07:42)

Previous to version 4.3 an empty string as the first parameter would not cause an error. Now checking to make sure the string is empty before calling number_format is needed.

Peter de Pijd (17-Aug-2009 04:35)

If you want to use nbsp as decimal/thousand delimiter with UTF-8 you have to replace the whitespace after using number_format:

<?php
$number
= number_format(1000, 0, ".", " "); // normal space
echo str_replace(" ", utf8_encode("\xA0"), $number);
// or
echo str_replace(" ", html_entity_decode("&nbsp;", ENT_COMPAT, "UTF-8"), $number);
?>

therealsix (03-Jul-2009 04:40)

I found you can add trailing zeroes simply by adding a float point value containing the number of decimal places you want to appear.

<?php
$number
= 5.2;
$number += .0000;
echo
$number;
?>

Outputs:
5.2000

info at daniel-marschall dot de (22-May-2009 08:54)

In my function my_number_format() [shown below] there was a bug.

If a negative number which is smaller than 1 was entered (-0,...), then the result was wrongly positive because +0 is equal to -0 (the content of $tmp[0] which was interpretet as numeric value).

Here is the corrected version:

<?php

function my_number_format($number, $dec_point, $thousands_sep)
{
   
$was_neg = $number < 0; // Because +0 == -0
   
$number = abs($number);

   
$tmp = explode('.', $number);
   
$out = number_format($tmp[0], 0, $dec_point, $thousands_sep);
    if (isset(
$tmp[1])) $out .= $dec_point.$tmp[1];

    if (
$was_neg) $out = "-$out";

    return
$out;
}

?>

Thanks to Federico Cassinelli for the bug report.



[EDIT BY danbrown AT php DOT net: The original note follows.]

Let's say we got the number $inp = 1234.56

By using

<?php
return number_format($inp, 2, ',', '.');
?>

you can get the German format 1.234,56. (Comma as decimal separator and point as thousand separator)

But I have a problem with that: I want to add commas as thousand separators and change the decimal-separator (this could also be done with str_replace), but I do not want to change the amount of fractional digits!

But since the 2nd argument of number_format is necessary to enter the 3rd and 4th argument, this cannot be done with number_format. You have to change the fractional digits with this function.

But I want that 1234.56 changes into 1.234,56 and 1234.567890123456 changes into 1.234,567890123456

So, I created following function, that doesn't change the amount of fractional digits:

<?php
function my_number_format($number, $dec_point, $thousands_sep)
{
 
$tmp = explode('.', $number);
 
$out = number_format($tmp[0], 0, $dec_point, $thousands_sep);
  if (isset(
$tmp[1])) $out .= $dec_point.$tmp[1];

  return
$out;
}
?>

james at bandit dot co.nz (27-Mar-2009 05:03)

Outputs a human readable number.

<?php
   
#    Output easy-to-read numbers
    #    by james at bandit.co.nz
   
function bd_nice_number($n) {
       
// first strip any formatting;
       
$n = (0+str_replace(",","",$n));
       
       
// is this a number?
       
if(!is_numeric($n)) return false;
       
       
// now filter it;
       
if($n>1000000000000) return round(($n/1000000000000),1).' trillion';
        else if(
$n>1000000000) return round(($n/1000000000),1).' billion';
        else if(
$n>1000000) return round(($n/1000000),1).' million';
        else if(
$n>1000) return round(($n/1000),1).' thousand';
       
        return
number_format($n);
    }
?>

Outputs:

247,704,360 -> 247.7 million
866,965,260,000 -> 867 billion

IMSoP (18-Mar-2009 10:36)

I'm not sure if this is the right place anyway, but "ben at last dot fm"'s ordinal function can be simplified further by removing the redundant "floor" (the result of floor is still a float, it's the "%" that's converting to int) and outer switch.

Note that this version also returns the number with the suffix on the end, not just the suffix.

<?php
function ordinal($num)
{
   
// Special case "teenth"
   
if ( ($num / 10) % 10 != 1 )
    {
       
// Handle 1st, 2nd, 3rd
       
switch( $num % 10 )
        {
            case
1: return $num . 'st';
            case
2: return $num . 'nd';
            case
3: return $num . 'rd'
        }
    }
   
// Everything else is "nth"
   
return $num . 'th';
}
?>

ben at last dot fm (27-Feb-2009 12:22)

Writing a function to get English ordinals for numbers is a problem every computer science student will face. Here's my solution - nice, short and simple:

<?php
   
function st($i) {
        switch(
floor($i/10) % 10 ) {
            default:
                switch(
$i % 10 ) {
                    case
1: return 'st';
                    case
2: return 'nd';
                    case
3: return 'rd';  
                }
            case
1:
        }
        return
'th';
    }
?>

Barbara (26-Jan-2009 07:04)

I was looking for a SIMPLE way to format currency and account for negative values while not losing the calculation properties of my number.  Here's my function - it's not rocket science, but maybe can help someone along the way.

<?php
function wims_currency($number) {
   if (
$number < 0) {
    
$print_number = "($ " . str_replace('-', '', number_format ($number, 2, ".", ",")) . ")";
    } else {
    
$print_number = "$ " number_format ($number, 2, ".", ",") ;
   }
   return
$print_number;
}
?>
Sample use:

<?php
$pur_po_total
=  ($pur_po_total + $pur_item_total);
$print_pur_po_total = wims_currency($pur_po_total);
?>

Returns (for example)    $ 44,561.00 or, if a negative ($ 407,250.00)

This way, I use my 1st variable for calculations and my 2nd variable for output.  I'm sure there are better ways to do it,  but this got me back on track.

thomas at weblizards dot de (23-Jan-2009 01:43)

It's not explicitly documented; number_format also rounds:

<?php
$numbers
= array(0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007, 0.008, 0.009);
foreach (
$numbers as $number)
    print
$number."->".number_format($number, 2, '.', ',')."<br>";
?>

0.001->0.00
0.002->0.00
0.003->0.00
0.004->0.00
0.005->0.01
0.006->0.01
0.007->0.01
0.008->0.01
0.009->0.01

nospam at nospam dot com (02-Dec-2008 10:08)

Simple function to show money as only dollars if no cents, but will show 2 decimals if cents exist.

The 'cents' flag can force to never or always show 2 decimals

<?php

// formats money to a whole number or with 2 decimals; includes a dollar sign in front
function formatMoney($number, $cents = 1) { // cents: 0=never, 1=if needed, 2=always
 
if (is_numeric($number)) { // a number
   
if (!$number) { // zero
     
$money = ($cents == 2 ? '0.00' : '0'); // output zero
   
} else { // value
     
if (floor($number) == $number) { // whole number
       
$money = number_format($number, ($cents == 2 ? 2 : 0)); // format
     
} else { // cents
       
$money = number_format(round($number, 2), ($cents == 0 ? 0 : 2)); // format
     
} // integer or decimal
   
} // value
   
return '$'.$money;
  }
// numeric
} // formatMoney

$a = array(1, 1234, 1.5, 1.234, 2.345, 2.001, 2.100, '1.000', '1.2345', '12345', 0, '0.00');

// show cents if needed ($cents=1)
foreach ($a as $b) echo ('<br />'.$b.' = '.formatMoney($b, 1));
1 = $1
1234
= $1,234
1.5
= $1.50
1.234
= $1.23
2.345
= $2.35
2.001
= $2.00
2.1
= $2.10
1.000
= $1
1.2345
= $1.23
12345
= $12,345
0
= $0
0.00
= $0

// never show cents ($cents=0)
foreach ($a as $b) echo ('<br />'.$b.' = '.formatMoney($b, 0));
1 = $1
1234
= $1,234
1.5
= $2
1.234
= $1
2.345
= $2
2.001
= $2
2.1
= $2
1.000
= $1
1.2345
= $1
12345
= $12,345
0
= $0
0.00
= $0

// always show cents ($cents=2)
foreach ($a as $b) echo ('<br />'.$b.' = '.formatMoney($b, 2));
1 = $1.00
1234
= $1,234.00
1.5
= $1.50
1.234
= $1.23
2.345
= $2.35
2.001
= $2.00
2.1
= $2.10
1.000
= $1.00
1.2345
= $1.23
12345
= $12,345.00
0
= $0.00
0.00
= $0.00

?>

Cheers :)

And remember to always contribute custom functions if they might be useful to the rest of us or future versions of the php language.

samuelpeixoto at gmail dot com (21-Nov-2008 01:05)

Exemplo: Example:

<?php
$number
= 1234567.896;
echo
'1: '.number_format($number, 2, ',', '').'<br>';
echo
'2: '.number_format($number, 2, '.', '').'<br>';
echo
'3: '.number_format($number, 2, ',', '.').'<br>';
echo
'4: '.number_format($number, 2, '.', ',').'<br>';
echo
'5: '.number_format($number, 2, ',', ' ').'<br>';
echo
'6: '.number_format($number, 2, ',', "'").'<br>';
echo
'7: '.number_format($number, 2, '', '').'<br>';
?>

Resultado: Result:

 1: 1234567,90   -> Decimal separado por ,
 2: 1234567.90   -> Decimal separado por .
 3: 1.234.567,90 -> Moeda Brasil, Alemanha
 4: 1,234,567.90 -> Inglês, USA
 5: 1 234 567,90 -> Fran?a
 6: 1'234'567,90 -> Suí?a
 7: 123456790    -> Sem decimal

with at held dot com (16-Sep-2008 07:17)

Note:
The accuracy tends to drift if you're setting a large decimal value.

<?php
$number
= 1234.560;
echo
number_format($number, 2, '.', '');
echo
number_format($number, 3, '.', '');
echo
number_format($number, 4, '.', '');
echo
number_format($number, 10, '.', '');
echo
number_format($number, 20, '.', '');
echo
number_format($number, 50, '.', '');
?>

echos this (for me at least).

1234.56
1234.560
1234.5600
1234.5600000000
1234.55999999999994543032
1234.55999999999994543031789362430572509765625000000000

SyCo

isapoetra at gmail dot com (15-Jun-2008 02:53)

here is the code to convert number to Indonesian text, this code has limitation as is number_format function. sorry for this.
/*
* Created : Iwan Sapoetra - Jun 13, 2008
* Project : Web
* Package : cgaf
*
*/
function terbilang( $num ,$dec=4){
    $stext = array(
        "Nol",
        "Satu",
        "Dua",
        "Tiga",
        "Empat",
        "Lima",
        "Enam",
        "Tujuh",
        "Delapan",
        "Sembilan",
        "Sepuluh",
        "Sebelas"
    );
    $say  = array(
        "Ribu",
        "Juta",
        "Milyar",
        "Triliun",
        "Biliun", // remember limitation of float
        "--apaan---" ///setelah biliun namanya apa?
    );
    $w = "";

    if ($num <0 ) {
        $w  = "Minus ";
        //make positive
        $num *= -1;
    }

    $snum = number_format($num,$dec,",",".");
    die($snum);
    $strnum =  explode(".",substr($snum,0,strrpos($snum,",")));
    //parse decimalnya
    $koma = substr($snum,strrpos($snum,",")+1);

    $isone = substr($num,0,1)  ==1;
    if (count($strnum)==1) {
        $num = $strnum[0];
        switch (strlen($num)) {
            case 1:
            case 2:
                if (!isset($stext[$strnum[0]])){
                    if($num<19){
                        $w .=$stext[substr($num,1)]." Belas";
                    }else{
                        $w .= $stext[substr($num,0,1)]." Puluh ".
                            (intval(substr($num,1))==0 ? "" : $stext[substr($num,1)]);
                    }
                }else{
                    $w .= $stext[$strnum[0]];
                }
                break;
            case 3:
                $w .=  ($isone ? "Seratus" : terbilang(substr($num,0,1)) .
                    " Ratus").
                    " ".(intval(substr($num,1))==0 ? "" : terbilang(substr($num,1)));
                break;
            case 4:
                $w .=  ($isone ? "Seribu" : terbilang(substr($num,0,1)) .
                    " Ribu").
                    " ".(intval(substr($num,1))==0 ? "" : terbilang(substr($num,1)));
                break;
            default:
                break;
        }
    }else{
        $text = $say[count($strnum)-2];
        $w = ($isone && strlen($strnum[0])==1 && count($strnum) <=3? "Se".strtolower($text) : terbilang($strnum[0]).' '.$text);
        array_shift($strnum);
        $i =count($strnum)-2;
        foreach ($strnum as $k=>$v) {
            if (intval($v)) {
                $w.= ' '.terbilang($v).' '.($i >=0 ? $say[$i] : "");
            }
            $i--;
        }
    }
    $w = trim($w);
    if ($dec = intval($koma)) {
        $w .= " Koma ". terbilang($koma);
    }
    return trim($w);
}
//example
echo terbilang(999999999999)."\n";
/**
 * result : Sembilan Ratus Sembilan Puluh Sembilan Milyar Sembilan Ratus Sembilan Puluh Sembilan Juta Sembilan Ratus Sembilan Puluh Sembilan Ribu Sembilan Ratus Sembilan Puluh Sembilan
 */
echo terbilang(9999999999999999);
/**
 * todo : fix this bug pleasese
 * problem : number_format(9999999999999999) <--- 10.000.000.000.000.000,0000
 * Result : Sepuluh Biliun
 */

xkeeper at gmail dot com (10-Jun-2008 06:26)

Technically, you can just use number_format() with "x" as the thousands seperator, then...

<?php
  str_replace
("x", "character of choice", number_format(1234.56, ".", "x"));
?>

This will probably be many times more efficient.

team at glossword dot biz (26-May-2008 02:45)

It's pity that the function supports one-byte characters only for "thousands separator".
For English it works well but for French and Russian it makes problem.
Developers should use character &#160; or chr(0xA0) as "thousands separator" to avoid the number of being moved to a new line in HTML-documents. But number_format() didn't understand that symbol.
To solve the problem, we wrote our own variant of number_format():

<?php
/* Replacement for number_format() */
function my_number_format($n, $decimals = 0, $dec_point = ',', $thousands_sep = '&#160;')
{
   
$b = explode('.', $n);
   
$rn = '';
   
$l = strlen($b[0]);
   
/* Reverse string */
   
for ($i = $l; $i > 3; $i -= 3)
    {
       
$rn = $thousands_sep . substr($b[0], $i - 3, 3) . $rn;
    }
   
/* sprintf() used to correct 0.79 to 0.790 */
    /* str_replace() used to correct decimals */
    /* str_repeat() used to correct decimals */
   
return substr($b[0], 0, $i) . $rn . ($decimals
           
? $dec_point.(isset($b[1])
                ?
str_replace('0.', '', sprintf('%0.'.$decimals.'f', '0.'.$b[1]))
                :
str_repeat(0, $decimals))
            :
'');
}
/* Outputs 123&#160;456,790 */
print my_number_format(123456.78987, 3);
?>

It can be optimized more, but this variant works well also.

gabrielu at gmail dot com (08-May-2008 05:54)

Using the number_format I'm having some unexpected results.  30% of 14.95 (14.95 * .3) = 4.485.  Now 4.485 rounded to two decimal places should give me 4.49.

Example:
<?php
echo number_format(14.95 * .3, 2, '.', '') . "\n";
echo
number_format(4.485, 2, '.', '') . "\n";
?>

Unexpected Results:
4.48
4.49

eregon at msn dot com (30-Jan-2008 09:02)

I have seen some scripts here for format a filesize, but i think this can be useful:

<?php
function format_filesize($number, $decimals = 3, $force_unit = false, $dec_char = ',', $thousands_char = ' ')
    {
//string format_filesize(int(0,) $number, (bool(0), int(0,4)) $force_unit, int $decimals, char $dec_char, char $thousands_char)
    //format a filesize $number with unit (setted by $force_unit(see below for the number))
       
$units = array('o', 'Ko', 'Mo', 'Go', 'To');
        if(
$force_unit === false)
           
$unit = floor(log($number, 2) / 10);
        else
           
$unit = $force_unit;
        if(
$unit == 0)
           
$decimals = 0;
        return
number_format($number / pow(1024, $unit), $decimals, $dec_char, $thousands_char).' '.$units[$unit];
    }
?>

ex:
format_filesize(2540367) => '2,423 Mo'
format_filesize(2540367, 2) => '2,42 Mo'
format_filesize(2540367, 1, 1) => '2 480,8 Ko' //0=>'o', 1=>'Ko', 2=>'Mo', 3=>'Go', 4=>'To' (see $units)
format_filesize(2540687367, 2, 1, ',', '.') => '2.481.140,01 Ko'

log($number, 2) / 10 = log($number, 1024) ;)
Fast & Easy, isn't it? :)

www.produkte24.com (08-Jan-2008 08:28)

I have to verify price data from several formats, eg:
- 12.345,67 (German)
- 12,345.67 (English)
- 12 345,67 (French)
- 12'345,67 (Swiss)

Here is a quick function which helps me out of all this format mess, but please not the I only check for:
- positive values
- max 2 digits on the right side (.12)

function mk_price_to_float($price){
    $price = trim($price);
    if(preg_match("~^([0-9]+|(?:(?:[0-9]{1,3}([.,' ]))+[0-9]{3})+)(([.,])[0-9]{1,2})?$~", $price, $r)){
        if(!empty($r['2'])){
            $pre = preg_replace("~[".$r['2']."]~", "", $r['1']);
        }else{
            $pre = $r['1'];
        }
        if(!empty($r['4'])){
            $post = ".".preg_replace("~[".$r['4']."]~", "", $r['3']);
        }else{
            $post = false;
        }
        $form_price = $pre.$post;
        return $form_price;
    }
    return false;
}

This code is used at http://www.produkte24.com/ and http://www.who-sells-it.com/ and works like a charm.

uliciadrian01 at yahoo dot com (06-Oct-2007 10:34)

A simple funtion to format american dollars.
<?
function formatMoney($money) {
    if($money<1) {
        $money='&cent;'.$money*100;
    }
    else {
        $dollars=intval($money);
        $cents=$money-$dollars;
        $cents=$cents*100;
        $money='$'.$dollars.' and &cent;'.$cents;
    }
    return $money;
}
echo formatmoney('52.342');
?>
This will output: "   $52 and ?34.2  ".

eb1024 at gmail dot com (12-Aug-2007 06:38)

To address the problems number_format has when dealing with big numbers I've created my own Number_Format method, it acts the same way as number_format and takes the same arguments but deals with numbers as strings solving the problems above referred.

(The other methods are available at http://www.alixaxel.com/wordpress/2007/05/19/php-math-library/)

function Number_Format($number, $decimal_precision = 0, $decimals_separator = '.', $thousands_separator = ',')
{
if ($this->Is_Negative($number))
{
    $negative = true;

    $number = str_replace('-', '', $number);
}

$number = explode('.', str_replace(' ', '', $number));

$number[0] = str_split(strrev($number[0]), 3);

$total_segments = count($number[0]);

for ($i = 0; $i < $total_segments; $i++)
{
    $number[0][$i] = strrev($number[0][$i]);
}

$number[0] = implode($thousands_separator, array_reverse($number[0]));

if ($negative === true)
{
    $number[0] = '-' . $number[0];
}

if (!empty($number[1]))
{
    $number[1] = $this->Round($number[1], $decimal_precision);
}

$number = implode($decimals_separator, $number);

return $number;
}

I hope this is useful for someone!

Jason Johnson (01-Aug-2007 08:39)

Beware of this pitfall:
$value = number_format ($float_val, 2, ".");

This will silently return an empty string and not throw an error, at least with PHP 5.x.

This is the corrected code:
$value = number_format ($float_val, 2, ".", ",");
- or -
$value = number_format ($float_val, 2);

You must specifiy either the decimal point AND thousands separator else neither, otherwise you'll run into this issue.

I just spent over 30min debugging code with this problem!

user at example dot net (16-Jul-2007 03:52)

The following function converts a string into Float or Integer while taking the given or locale number format into account.

<?php

   
function strtonumber( $str, $dec_point=null, $thousands_sep=null )
    {
        if(
is_null($dec_point) || is_null($thousands_sep) ) {
           
$locale = localeconv();
            if(
is_null($dec_point) ) {
               
$dec_point = $locale['decimal_point'];
            }
            if(
is_null($thousands_sep) ) {
               
$thousands_sep = $locale['thousands_sep'];
            }
        }
       
$number = (float) str_replace($dec_point, '.', str_replace($thousands_sep, '', $str));
        if(
$number == (int) $number ) {
            return (int)
$number;
        } else {
            return
$number;
        }
    }

?>

alx at inbox dot lv (15-May-2007 10:14)

enjoy the PHP!
<?php
function FormatPrice($price) {
   
$price = preg_replace("/[^0-9\.]/", "", str_replace(',','.',$price));
    if (
substr($price,-3,1)=='.') {
       
$sents = '.'.substr($price,-2);
       
$price = substr($price,0,strlen($price)-3);
    } elseif (
substr($price,-2,1)=='.') {
       
$sents = '.'.substr($price,-1);
       
$price = substr($price,0,strlen($price)-2);
    } else {
       
$sents = '.00';
    }
   
$price = preg_replace("/[^0-9]/", "", $price);
    return
number_format($price.$sents,2,'.','');
}
?>

Joeri (13-Feb-2007 03:18)

Aj and astrolox, for perfect precision arithmetic, you can use the bcmath functions, which perform math on string representations of numbers, instead of on floats. Obviously this is an order of magnitude slower, but at least you don't lose any precision due to the complexities of IEEE-754.

ted at qtis dot co dot nz (07-Feb-2007 11:38)

I use the following to get around the negative zero problem:

function currency_format($amount, $precision = 2, $use_commas = true, $show_currency_symbol = false, $parentheses_for_negative_amounts = false)
{
    /*
    **    An improvement to number_format.  Mainly to get rid of the annoying behaviour of negative zero amounts.   
    */
    $amount = (float) $amount;
    // Get rid of negative zero
    $zero = round(0, $precision);
    if (round($amount, $precision) == $zero) {
        $amount = $zero;
    }
   
    if ($use_commas) {
        if ($parentheses_for_negative_amounts && ($amount < 0)) {
            $amount = '('.number_format(abs($amount), $precision).')';
        }
        else {
            $amount = number_format($amount, $precision);
        }
    }
    else {
        if ($parentheses_for_negative_amounts && ($amount < 0)) {
            $amount = '('.round(abs($amount), $precision).')';
        }
        else {
            $amount = round($amount, $precision);
        }
    }
   
    if ($show_currency_symbol) {
        $amount = '$'.$amount;  // Change this to use the organization's country's symbol in the future
    }
    return $amount;
}

zulisse at email dot it (06-Feb-2007 10:27)

simpler function to convert a number in bytes, kilobytes....

<?php

function bytes($a) {
   
$unim = array("B","KB","MB","GB","TB","PB");
   
$c = 0;
    while (
$a>=1024) {
       
$c++;
       
$a = $a/1024;
    }
    return
number_format($a,($c ? 2 : 0),",",".")." ".$unim[$c];
}

?>

you may also add others units over PeraBytes when the hard disks will reach 1024 PB :)

lathem at gibsoncomputer dot net (22-Dec-2006 05:41)

I've discovered that the commas which number_format() inserts as a thousands separators causes math functions to break. 

Bit of a newbie thing, but it bit me in the ass.

eg--

<?
$foo = number_format(1234, 2);
?>

$foo is now equal to 1,234.00

<?
$bar = 23;
$result = $foo+$bar;
?>

One would think $result == 1,257.00.  However, because number_format added a comma to $foo, the expression will not evaluate correctly. 

Instead, do things in this order:

<?
$foo=1234;
$bar=23;
$foobar=number_format($foo+$bar, 2);
?>

$foobar is now set to 1,257.00.

Another method, if you're fixing code you've already written and don't want to change a huge amount, is to remove the thousands separator, using the appropriate variable to number_format. 

<?
$foo = number_format(1234, 2, '.', '');
$bar = number_format(23, 2, '.', '');
$foobar = number_format($foo+$bar, 2);
?>

$foobar will now be set to 1,257.00

webmaster at WWW.ELLESSEWEB.NET (24-Nov-2006 02:51)

This is a simple and useful function to convert a byte number in a KB  or MB:

<?
function filesize_format ($bytes) {
  $bytes=(float)$bytes;
  if ($bytes<1024){
  $numero=number_format($bytes, 0, ',', '.')." Byte";
  return $numero;
  }
  if ($bytes<1048576){
      $numero=number_format($bytes/1024, 2, ',', '.')." KByte";
  return $numero;
  }
  if ($bytes>=1048576){
      $numero=number_format($bytes/1048576, 2, ',', '.')." MByte";
  return $numero;
  }
}
?>

giovanni dot cappellini at gmail dot com (26-Oct-2006 03:31)

About the function of j-a-n at gmx dot de: it's useful, but the argument of the function is $number while the logic of the function requires it to be $in.

dwhitaker at dfwairport dot com (13-Sep-2006 03:56)

You know sometimes we forget to add the basic cool stuff...

Found this over in the money_format section and felt some newbie is probably looking for it...

$val = "1000000";
echo number_format($val, 0, "", ","); // returns 1,000,000

(26-Aug-2006 12:45)

Unfortunately, this function is not multibyte-safe. If you want to use the typographically correct separator for thousands in Swiss German and UTF-8 (‘ - Unicode 2019), you'll only get the first byte - e.g. garbage -  since this function strips anything after the first byte, regardless of the charset used.

j-a-n at gmx dot de (10-Aug-2006 06:04)

This function formats an decimal number to a String.
But it does'n use an fixed count of decimals but calculates the needed count of decimals.

<?
function formatNumber( $number, $decimals=2, $dec_point=".", $thousands_sep=",") {
    $nachkomma = abs($in - floor($in));
    $strnachkomma = number_format($nachkomma , $decimals, ".", "");

    for ($i = 1; $i <= $decimals; $i++) {
        if (substr($strnachkomma, ($i * -1), 1) != "0") {
            break;
        }
    }
   
    return number_format($in, ($decimals - $i +1), $dec_point, $thousands_sep);
}
?>
Example:

formatNumber( 100.00 );
--> 100
formatNumber( 100.50 );
--> 100.5
formatNumber( 100.1234 );
--> 100.12
formatNumber( 100.12, 4 );
--> 100.12
formatNumber( 100.12345, 4 );
--> 100.1234

(04-Jun-2006 08:55)

The modification to number_format below does what I actually want it to do, with currency, for example. I want it to show $1.40 and not $1.4 or $1.400 - except in the rare case where I have $1.435 for something, in which case I *don't* want it to round. The ugliness below serves my purpose.

function nof($number,$decimals) {
if (number_format($number,$decimals,'.',',') != $number) {
        return $number;
} else {
        return number_format($number,$decimals,'.',',');
        }
}

ck at vowel dot se (26-May-2006 11:11)

Again, the function for returning file size in human readable format, but with a tweek for displaying one decimal when size is less than 10 units.

<?php
function human_readable( $size )
{
  
$count = 0;
  
$format = array("B","KB","MB","GB","TB","PB","EB","ZB","YB");
   while((
$size/1024)>1 && $count<8)
   {
      
$size=$size/1024;
      
$count++;
   }
   if(
$size < 10 ) $decimals = 1;
   else
$decimals = 0;
  
$return = number_format($size,$decimals,'.',' ')." ".$format[$count];
   return
$return;
}
?>

Thanks to "php dot net at alan-smith dot no-ip dot com" and "service at dual-creators dot de".

rudie at jouwmoeder dot nl (22-May-2006 10:30)

number_format is pretty fast. It's much slower than calculation though:
<?php

$start
= microtime(true);

echo
"<pre>";
for (
$i=0;$i<100000;$i++)
{
    echo
number_format(microtime(true)-$start,25)."\n";
}
echo
"<hr />Parsetime: ".(microtime(true)-$start);

?>
This takes 1.03 seconds all the time. Without the -$start in the number_format cmd, it takes exactly as long (I ran it about 20 times).
The simple calculation inside number_format takes relatively no time. Defining the number before entering it into number_format also gives no change:
{
    $num = microtime(true)-$start;
    echo number_format($num,25)."\n";
}

Which concludes it takes about .01 sec to do a thousand number_format.
If you'd do the same routine without the number_format, it'd take .75 seconds -> number_format very fast!

gfinale at hotmail dot com (14-May-2006 06:58)

Thanks to armstrong ~~at~~ rice ~~dot~~ edu for your number to words function.  There does seem to be one glitch I've discovered, at least on my system.  Hundreds work but hundreds of thousands and hundreds of millions do not.  e.g. 100,000 or 100,000,000 hangs.

chris_cember at cinmach dot com (15-Mar-2006 09:40)

// the mktime shortcut is a little trickier than it would first appear, even with a mod...

function text_number($n) {
    $mod = $n % (($n > 20)?10:20);
    return $n . (($mod==0)?"th":date("S",mktime(0,0,0,1,$mod,2000)));
}  

// or for those who don't appreciate shorthand:

function text_number($n) {
    if ($n > 20) {
        $mod_factor = 10;
    } else {
        $mod_factor = 20;
    }  
    $mod = $n % $mod_factor;
    if ($mod == 0) {
        $txt = "th";
    } else {
        $txt = date("S",mktime(0,0,0,1,$mod,2000));
    }  
    return $n . $txt;
}

/*
one issue comes up in numbers that mod to zero (which mktime will associate with the 31st of December, 1999).  another issue is between 23rd and 13rd, err I mean 13th.  If you use 20 (or even 30) all the time, however, you'll end up with 33th (or 43th).
*/

Steve Neill (04-Mar-2006 12:04)

actually, you'd want to MOD the number to get it within a useful range first (1 .. 30).

Enjoy.

mikesabatino at gmail dot com (01-Mar-2006 03:34)

<?php
# Function to represent a number like '2nd', '10th', '101st' etc
function text_number($n)
{
   
# Array holding the teen numbers. If the last 2 numbers of $n are in this array, then we'll add 'th' to the end of $n
   
$teen_array = array(11, 12, 13, 14, 15, 16, 17, 18, 19);
   
   
# Array holding all the single digit numbers. If the last number of $n, or if $n itself, is a key in this array, then we'll add that key's value to the end of $n
   
$single_array = array(1 => 'st', 2 => 'nd', 3 => 'rd', 4 => 'th', 5 => 'th', 6 => 'th', 7 => 'th', 8 => 'th', 9 => 'th', 0 => 'th');
   
   
# Store the last 2 digits of $n in order to check if it's a teen number.
   
$if_teen = substr($n, -2, 2);
   
   
# Store the last digit of $n in order to check if it's a teen number. If $n is a single digit, $single will simply equal $n.
   
$single = substr($n, -1, 1);
   
   
# If $if_teen is in array $teen_array, store $n with 'th' concantenated onto the end of it into $new_n
   
if ( in_array($if_teen, $teen_array) )
    {
       
$new_n = $n . 'th';
    }
   
# $n is not a teen, so concant the appropriate value of it's $single_array key onto the end of $n and save it into $new_n
   
elseif ( $single_array[$single] )
    {
       
$new_n = $n . $single_array[$single];   
    }
   
   
# Return new
   
return $new_n;
}
?>

MarcM (21-Feb-2006 06:03)

For Zero fill - just use the sprintf() function

$pr_id = 1;
$pr_id = sprintf("%03d", $pr_id);
echo $pr_id;

//outputs 001
-----------------

$pr_id = 10;
$pr_id = sprintf("%03d", $pr_id);
echo $pr_id;

//outputs 010
-----------------

You can change %03d to %04d, etc.

adnan 'at' barakatdesigns 'dot' net (30-Jan-2006 03:43)

Just a note to the author of the "zerofill" function, you may find it easier using the str_pad function

<?php
$num
= 4;
$zerofill = 3;

echo
str_pad($num, $zerofill, "0", STR_PAD_LEFT);

/* Returns the same wanted result of '004' */
?>

versae arroba gmail punto com (24-Jan-2006 11:17)

A modification for kolnedra's function

<?

function humanReadable($val, $miles = 0){
    if($val>=1000)
        $val = humanReadable($val / 1024, ++$miles);
    else {
        $unidad = array('','K','M','G','T','P','E','Z','Y',
        'X','W','V','U','TD','S','R',
        'Q','PP','O','N','MI','L');
        $val = round($val, 2).$unidad[$miles].'B';
    }
    return $val;
}

?>

(20-Jan-2006 08:48)

A function to return a number with needed zeros at the beginning. Called "zerofill"

<?php
// $num = 4; $zerofill= 3; returns "004"
function zerofill ($num,$zerofill) {
    while (
strlen($num)<$zerofill) {
       
$num = "0".$num;
    }
    return
$num;
}
?>

YumYum (11-Jan-2006 06:19)

Jarrat's example below has a problem.  If the number is negative, the sign is dropped.  It always returns positive numbers.  The problem seems to be in the float cast in:

return (float) $number[0].'.'.$decimal;

I have not had a problem in PHP5 with:

return $number[0].'.'.$decimal;

Sprille (21-Dec-2005 04:45)

as response to mike at phpeeb dot com.

You can do aritmetic even on strings, you just need a little function to sort it out like this :

function str2no($number){
  $number = str_replace(".", "", $number);
  $number = str_replace(",", ".", $number);
  return $number;
}

function no2str($number){
  $number = number_format($number,2, ',', '.');
  return $number;
}
 
echo no2str(str2no("1.200,50")*3);

// we use 1200.50 as input "1.200,50" is the danish string for this number
//this will output 3601.50 with right formatting = 3.601,50 as string
//nice to know when dealing with money.

kolnedra at gmail dot com (10-Oct-2005 02:28)

A way to let a number (in this case an ammount of money) be shown in dutch annotation:
<?
// geld(123) >>> 123
// geld(123456) >>> 1.234.567
function geld($nm) {
    for ($done=strlen($nm); $done > 3;$done -= 3) {
        $returnNum = ".".substr($nm,$done-3,3).$returnNum;
    }
    return substr($nm,0,$done).$returnNum;
}
?>

mikro_at_teppisti_dot_it (05-Oct-2005 12:04)

This function formats numbers 'human readable' better (IMHO) than mircea way:

function humanReadable($val,$thousands=0){
   if($val>=1000)
     $val=humanReadable($val/1024,++$thousands);
   else{
     $unit=array('','K','M','T','P','E','Z','Y');
     $val=round($val,2).$unit[$thousands].'B';
   }
   return $val;
 }

Jeroen de Bruijn [NL] (01-Oct-2005 11:02)

If you want to display a number ending with ,- (like 200,-) when there are no decimal characters and display the decimals when there are decimal characters i use:

function DisplayDouble($value)
  {
  list($whole, $decimals) = split ('[.,]', $value, 2);
  if (intval($decimals) > 0)
    return number_format($value,2,".",",");
  else
    return number_format($value,0,".",",") .",-";
  }

astrolox at lawyersonline dot co dot uk (01-Aug-2005 04:34)

Users should be aware of the following behaviour.
I'm not sure if this is a PHP bug, libc bug, or if it's even a bug at all. So I thought I'd make a comment and allow everyone else to make up their own minds.

FreeBSD 4.3 PHP 4.3.3

<?php

// the comments show the output generated by this script

echo "input 8.525 output = ". number_format( 8.525, 2, '.', "") ."\n";
echo
"input 8.525 output = ". number_format(8.525, 2, '.', "") ."\n";

// input 8.525 output = 8.53
// input 8.525 output = 8.53

$a = 483.00;
$b = 0.175;

$c = $a * $b;

echo
"input \$c = $c type ". gettype($c) ." output = ". number_format( $c, 2, '.', "") ."\n";

// input $c = 84.525 type double output = 84.52

$d = 17.5;

$e = ( $a / 100 ) * $d;

echo
"input \$e = $e type ". gettype($e) ." output = ". number_format( $e, 2, '.', "") ."\n";

// input $e = 84.525 type double output = 84.53

echo "input 63.745 output = ". number_format(63.745, 2, '.', "") ."\n";
echo
"input 64.745 output = ". number_format(64.745, 2, '.', "") ."\n";
echo
"input 65.745 output = ". number_format(65.745, 2, '.', "") ."\n";

// input 63.745 output = 63.74
// input 64.745 output = 64.75
// input 65.745 output = 65.75

?>

jarratt at si-works dot net (15-Jul-2005 11:06)

With one of the payment providers they required a monitary input of 12345.67 always with a 2 decimal placing even if .00

if you have a number 12345.5 with only one decimal place i could find no sutable php function to guarentee two decimal palces and add a trailing zero if required,

This fucntion should assist

function format_number($str,$decimal_places='2',$decimal_padding="0"){
        /* firstly format number and shorten any extra decimal places */
        /* Note this will round off the number pre-format $str if you dont want this fucntionality */
        $str           =  number_format($str,$decimal_places,'.','');     // will return 12345.67
        $number       = explode('.',$str);
        $number[1]     = (isset($number[1]))?$number[1]:''; // to fix the PHP Notice error if str does not contain a decimal placing.
        $decimal     = str_pad($number[1],$decimal_places,$decimal_padding);
        return (float) $number[0].'.'.$decimal;
}

/* examples */

format_number('1234');       // -->   1234.00
format_number('1234.5');     //-->   1234.50
format_number('1234.567');  //-->   1234.57

marc dot vanwoerkom at fernuni-hagen dot de (14-Jul-2005 02:53)

See also the documentation for localeconv, which will provide values for decimal point and thousands separator from the C standard library.

Of course localeconv features many more locale information, like indicating to put the negative sign behind the value for some locale settings which can't be used to customize present number_format.

venimus777 at yahoo dot com (08-Jun-2005 01:25)

You could use the following regular expression to divide
a number into parts:

$1-number without fractal part
$2-fractal part
$3-first 2 digits of the fractal part
$4-rest of the fractal part

the regex removes any leading and trailing symbols and leading zeros. It doesnt validate the number, so 12 41 is considered to be correct input!

english notation:
/^.*?[0]*([\d\s]+)(([\.][\d]{0,2})([\d]*))?.*?$/

french notation:
/^.*?[0]*([\d\s]+)(([\,][\d]{0,2})([\d]*))?.*?$/

<?php
// truncate the fractal part up to 2 digits of an "english number":
$number = '01,234.50789';
$trunc = preg_replace(
   
'/^.*?[0]*([\d\,]+)(([\.][\d]{0,2})([\d]*))?.*?$/',
   
'$1$3',
   
$number
);
echo
$trunc;
?>

Outputs:
1,234.50

$number='e00012 41.100001e-4fasfd';
would output:
12 41.10

woodynadobhar at hotmail dot com (17-May-2005 05:04)

What do you do if some of your numbers have decimal places, and some don't?  You can switch between functions, but if you're building it in a loop, that's not a good solution.  Instead, we have the same as below, with a slight change:

function number_format_unlimited_precision($number,$decimal = '.'){
    $broken_number = explode($decimal,$number);
    if($broken_number[1]==0){
        return number_format($broken_number[0]);
    }else{
        return number_format($broken_number[0]).$decimal.$broken_number[1];
    };
};

stm555 at hotmail dot com (27-Apr-2005 04:54)

I ran across an issue where I wanted to keep the entered precision of a real value, without arbitrarily rounding off what the user had submitted.

I figured it out with a quick explode on the number before formatting. I could then format either side of the decimal.

<?php
     
function number_format_unlimited_precision($number,$decimal = '.')
      {
          
$broken_number = explode($decimal,$number);
           return
number_format($broken_number[0]).$decimal.$broken_number[1];
      }
?>

mike at phpeeb dot com (02-Apr-2005 09:13)

Since number_format returns a string, you must perform all mathmatical functions on the number before applying number_format:

<?
$total = 100;
$total = number_format($total, 2);
$shipping = 20.00;
$grand_total = $total + $shipping;

echo number_format($grand_total, 2);

/* The above will return 21.00 because $total is now a string, and no longer an integer or float. Since a string will have a value of 1,  the addition of the two will return 21 and not 120. */

$total = 100;
$shipping = 20.00;
$grand_total = $total + $shipping;

echo number_format($grand_total, 2);

/* This works, and will return 120.00 as intended */

?>

php at mijav dot dk (31-Mar-2005 02:25)

A bug was issued that -0,00 is invalid output from number_format(), but the bug was rejected since the number "-0.0000000000000000001E-999 is about -0". And the developer felt this was correct output.

Please beware of negative numbers close to zero, as they might produce this unusable (and in my opinion incorrect/off-description) output.

ChronoFish (23-Mar-2005 07:14)

I was looking for an easy way to take a number (or string) and force into a specific format.  I came up with.  I apologize if this is redundant, but I could not find a simular function:

/***********************************
* string_format
***********************************/
function string_format($format, $string, $placeHolder = "#")
{           
    $numMatches = preg_match_all("/($placeHolder+)/", $format, $matches);             
    foreach ($matches[0] as $match)
    {
        $matchLen = strlen($match);
        $format = preg_replace("/$placeHolder+/", substr($string, 0, $matchLen), $format, 1);
        $string = substr($string, $matchLen);
    }
    return $format;
}

To Use:

print string_format("(###)###-####", "4015551212");
will print out:
(401)555-1212

Hope this helps someone,

CF

tonywebman at NOSPAM dot telusplanet dot net (23-Feb-2005 09:14)

While trying to add variables whose values had been processed with number_format() I found an interesting gotcha. Perhaps this might help others.

Since number_format() returns a string, numbers returned that DO NOT have a comma in them will still be added but numbers that DO have a comma will not be added because PHP considers them a string and ignores them.

e.g. #1
$quant_mag = 1;
$cost_mag = 100;
$quant_ffr = 1
$cost_ffr = 100;

$ext_mag = number_format($quant_mag * $cost_mag,2);
$ext_ffr = number_format($quant_ffr * $cost_ffr,2);

$total_cost = $ext_mag + $ext_ffr;

// $total cost is: 200

e.g. #2
$quant_mag = 10;
$cost_mag = 100;
$quant_ffr = 1
$cost_ffr = 100;

$ext_mag = number_format($quant_mag * $cost_mag,2);
$ext_ffr = number_format($quant_ffr * $cost_ffr,2);

$total_cost = $ext_mag + $ext_ffr;
// $total cost is: 100 (not 1100 as you would expect) because $ext_mag is ignored because php interprets its value (1,000) as a string so it won't add it to $ext_ffr.

keyg at auralplanet dot com (23-Nov-2004 02:56)

if you want &nbsp; as a separator and use windows charset this piece of code may help:

<?php
$number
=number_format($number,2,'.',chr(0xA0));
?>

brandonprudent at yahoo dot com (10-Oct-2004 07:52)

To convert numbers to thier textual representations, you can use an adapted version of the Number::Spell Perl module. The PHP conversion can be found here: http://pear.php.net/package/Numbers_Words

GeekPrices Dot Com (07-Oct-2004 01:57)

this also works as well

$number = "29346.99"; //value
echo "$" .number_format($number, 2, '.', ',');

produces $29,346.99

Svein Tjonndal (sveint at yahoo dot com) (15-Sep-2004 03:18)

If you use space as a separator, it will break on that space in HTML tables...

Furthermore, number_format doesn't like '&nbsp;' as a fourth parameter. I wrote the following function to display the numbers in an HTML table.

  function numberfix($number)
  {
    $number = number_format($number,0,","," ");
    return str_replace(" ", "&nbsp;", $number);
  }

For use in:
<table><tr><td><?php echo $number; ?></td></tr></table>

drew at zitnay dot com (17-Aug-2004 07:17)

A more reliable and concise way of doing what S. Rahmel was trying to do below is as follows:

<?php
$field_inhalt
= str_replace(array(".", ","), array("", "."), $field_inhalt);
?>

The str_replace() call will first replace all dots with blanks, and then replace all commas with dots.  That way, it doesn't break down when you try a number over one million (i.e. 1.010.453,21).

Drew

mircea at vtds dot co dot uk (02-Jun-2004 05:57)

This function formats numbers 'human readable':

function byte_format($input, $dec=0)
{
  $prefix_arr = array(" B", "K", "M", "G", "T");
  $value = round($input, $dec);
  $i=0;
  while ($value>1024)
  {
     $value /= 1024;
     $i++;
  }
  $return_str = round($value, $dec).$prefix_arr[$i];
  return $return_str;
}

S. Rahmel (11-Mar-2004 10:47)

if you converted a number to a German format with number_format() and want to save it in mySQL, you first have to change the number format back to an English format.

For example
10.453,21 >>>> 10453.21

Here is an example how to do this:

    $field_array=explode(".", $field_inhalt);
    $field_inhalt=$field_array[0].$field_array[1];
    $foeld_array=explode(",", $field_inhalt);
    $field_inhalt=$field_array[0].".".$feld_array[1];
    $field_inhalt=sprintf($field_inhalt, 2);

$field_inhalt is the variable of the actual number you want to change to the english format.

chandu at chandu dot org (08-Mar-2004 01:29)

People here in India are more used to counting money in Lakhs & Crores .. so here is the code for formatting the commas with thousands for the first time and then with hundred multiples from there after.

Ex: 1234567  ->  12,34,567

<?php

function makecomma($input)
{
   
// This function is written by some anonymous person - I got it from Google
   
if(strlen($input)<=2)
    { return
$input; }
   
$length=substr($input,0,strlen($input)-2);
   
$formatted_input = makecomma($length).",".substr($input,-2);
    return
$formatted_input;
}

function
formatInIndianStyle($num){
   
// This is my function
   
$pos = strpos((string)$num, ".");
    if (
$pos === false) { $decimalpart="00";}
    else {
$decimalpart= substr($num, $pos+1, 2); $num = substr($num,0,$pos); }

    if(
strlen($num)>3 & strlen($num) <= 12){
               
$last3digits = substr($num, -3 );
               
$numexceptlastdigits = substr($num, 0, -3 );
               
$formatted = makecomma($numexceptlastdigits);
               
$stringtoreturn = $formatted.",".$last3digits.".".$decimalpart ;
    }elseif(
strlen($num)<=3){
               
$stringtoreturn = $num.".".$decimalpart ;
    }elseif(
strlen($num)>12){
               
$stringtoreturn = number_format($num, 2);
    }

    if(
substr($stringtoreturn,0,2)=="-,"){$stringtoreturn = "-".substr($stringtoreturn,2 );}

    return
$stringtoreturn;
}

$num = 1234567;
echo 
formatInIndianStyle($num);

?>

armstrong ~~at~~ rice ~~dot~~ edu (23-Feb-2004 12:33)

I submitted this question earlier, but I found the answer myself.  To convert a number to its word form (e.g. 34 to "thirty four")  try the function below.  It turned out to be a lot more complex than I thought!

I'm using it for printing dollar ammounts, so the cents get printed like 13/100

I converted most of it from this java code http://mindprod.com/inwords.html so credit goes to him for doing the hard part.

<?
/**
* convert long integer into American English words.
* e.g. -12345 -> "minus twelve thousand forty-five"
* Handles negative and positive integers
* on range -Long.MAX_VALUE .. Long.MAX_VALUE;
* It cannot handle Long.MIN_VALUE;
*/

function num2words( $num ){
    $ZERO = "zero";
    $MINUS = "minus";
    $lowName = array(
          /* zero is shown as "" since it is never used in combined forms */
          /* 0 .. 19 */
          "", "one", "two", "three", "four", "five",
          "six", "seven", "eight", "nine", "ten",
          "eleven", "twelve", "thirteen", "fourteen", "fifteen",
          "sixteen", "seventeen", "eighteen", "nineteen");

    $tys = array(
          /* 0, 10, 20, 30 ... 90 */
          "", "", "twenty", "thirty", "forty", "fifty",
          "sixty", "seventy", "eighty", "ninety");

    $groupName = array(
          /* We only need up to a quintillion, since a long is about 9 * 10 ^ 18 */
          /* American: unit, hundred, thousand, million, billion, trillion, quadrillion, quintillion */
          "", "hundred", "thousand", "million", "billion",
          "trillion", "quadrillion", "quintillion");

    $divisor = array(
          /* How many of this group is needed to form one of the succeeding group. */
          /* American: unit, hundred, thousand, million, billion, trillion, quadrillion, quintillion */
          100, 10, 1000, 1000, 1000, 1000, 1000, 1000) ;

    $num = str_replace(",","",$num);
    $num = number_format($num,2,'.','');
    $cents = substr($num,strlen($num)-2,strlen($num)-1);
    $num = (int)$num;

    $s = "";

    if ( $num == 0 ) $s = $ZERO;
    $negative = ($num < 0 );
    if ( $negative ) $num = -$num;

    // Work least significant digit to most, right to left.
    // until high order part is all 0s.
    for ( $i=0; $num>0; $i++ ) {
        $remdr = (int)($num % $divisor[$i]);
        $num = $num / $divisor[$i];
        // check for 1100 .. 1999, 2100..2999, ... 5200..5999
        // but not 1000..1099,  2000..2099, ...
        // Special case written as fifty-nine hundred.
        // e.g. thousands digit is 1..5 and hundreds digit is 1..9
        // Only when no further higher order.
        if ( $i == 1 /* doing hundreds */ && 1 <= $num && $num <= 5 ){
            if ( $remdr > 0 ){
                $remdr += $num * 10;
                $num = 0;
            } // end if
        } // end if
        if ( $remdr == 0 ){
            continue;
        }
        $t = "";
        if ( $remdr < 20 ){
            $t = $lowName[$remdr];
        }
        else if ( $remdr < 100 ){
            $units = (int)$remdr % 10;
            $tens = (int)$remdr / 10;
            $t = $tys [$tens];
            if ( $units != 0 ){
               $t .= "-" . $lowName[$units];
            }
        }else {
            $t = $inWords($remdr);
        }
        $s = $t . " " . $groupName[$i] . " "  . $s;
        $num = (int)$num;
    } // end for
    $s = trim($s);
    if ( $negative ){
        $s = $MINUS . " " . $s;
    }

    $s .= " and $cents/100";

    return $s;
} // end inWords

?>

cruzf_AT_fibertel.com.ar (07-Nov-2003 07:03)

You could add padding zeros like this:

<?
$number="129";
$number=sprintf("%08d",$number);
?>

j dot bos at bytewriters dot nl (01-Jun-2003 08:45)

If I'm not mistaking all these examples of adding leading zeros will not really work with floats. Sometimes though one needs it to have it working with floats as well.

With the function below use 2, 3 or 5 parameters. Don't ask me why 4 don't work, the number_format() function seems to have problems with that. At least my version of PHP has that "feature".

function leading_zero( $aNumber, $intPart, $floatPart=NULL, $dec_point=NULL, $thousands_sep=NULL) {        //Note: The $thousands_sep has no real function because it will be "disturbed" by plain leading zeros -> the main goal of the function
  $formattedNumber = $aNumber;
  if (!is_null($floatPart)) {    //without 3rd parameters the "float part" of the float shouldn't be touched
    $formattedNumber = number_format($formattedNumber, $floatPart, $dec_point, $thousands_sep);
    }
  //if ($intPart > floor(log10($formattedNumber)))
    $formattedNumber = str_repeat("0",($intPart + -1 - floor(log10($formattedNumber)))).$formattedNumber;
  return $formattedNumber;
  }

echo leading_zero(21.12345678, 4, 5);    // Output: 0021.12346
echo leading_zero(21.12345678, 4);    // Output: 0021.12345678
echo leading_zero(21.12345678, 3, 0); // Output: 021
echo leading_zero(21.12345678, 3, 5, ",", ""); // Output: 021,12346

addition: Just like the number_format I haven't found a way *not* to round a number while changing the decimal point and the thousands seperator.

sgj at dr dot com (18-May-2003 02:04)

Just an observation:
The number_format rounds the value of the variable.

$val1 = 1.233;
$val2 = 1.235;
$val3 = 1.237;

echo number_format($val1,2,",","."); // returns: 1,23
echo number_format($val2,2,",","."); // returns: 1,24
echo number_format($val3,2,",","."); // returns: 1,24

Theo Diem (24-Mar-2003 09:45)

formatting numbers may be more easy if u use number_format function.

I also wrote this :
function something($number)
{
    $locale = localeconv();
    return number_format($number,
       $locale['frac_digits'],
        $locale['decimal_point'],
        $locale['thousands_sep']);
}

hope this helps =)
[]'s

andrew at crucible dot co dot nz (05-Jan-2002 12:56)

Remember that number_format returns a string, so you shouldn't run a number_format on a variable that's already a product of number_format (it will only take the first token of the string)...

eg. echo number_format("123,456.00", 2);
produces: 123.00

sctemplarknight at hotmail dot com (12-Dec-2001 09:27)

number_format($number,$precision,".","") should be used when setting the value of form elements because if you read the number into a double upon submission, it will only store digits before the comma.
<p>
ie. <input type="text" value="<?php echo(number_format(2.5343,2,".","")">