768

What's the correct way to round a PHP string to two decimal places?

$number = "520"; // It's a string from a database

$formatted_number = round_to_2dp($number);

echo $formatted_number;

The output should be 520.00;

How should the round_to_2dp() function definition be?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rich Bradshaw
  • 71,795
  • 44
  • 182
  • 241
  • 19
    This really isn't "rounding". Rounding _reduces_ precision. It will not add decimal places to a number that doesn't have them. Based on many of the answers and comments, it seems like people are thinking that rounding is something it isn't. `round` is a math function, and this is just a formatting problem. – Don't Panic Feb 14 '17 at 18:18

24 Answers24

1451

You can use number_format():

return number_format((float)$number, 2, '.', '');

Example:

$foo = "105";
echo number_format((float)$foo, 2, '.', '');  // Outputs -> 105.00

This function returns a string.

Codemwnci
  • 54,176
  • 10
  • 96
  • 129
  • 8
    round() would be better for it's readability and simplicity too, but for anything critical be aware that it has been known to be buggy – StringsOnFire Feb 26 '14 at 22:07
  • 67
    @ÁlvaroG.Vicario `round` doesn't solve the OP's problem here. `round("520", 2)` returns the float `520`, and echoing that will of course not show it to 2 decimal places. For the OP's purpose - showing an integer to 2 decimal places by padding it with trailing zeroes - you need a number formatting function, not a rounding function. – Mark Amery Mar 16 '14 at 21:38
  • 4
    All the other answers are limited to decimal values with a dot notation. When you need to get `520,00` instead of `520.00`, this simply works. – SPRBRN May 08 '14 at 15:06
  • 1
    if you want to limit only float but not int then bcdiv($number,1,2) – Wasim A. Feb 26 '16 at 11:53
  • 1
    I don't think if it's because i am using `php 7.1.0` but the float-casting seems useless in my case and adding or removing will have no effect to the end result. – vdegenne Jan 18 '17 at 22:45
  • 4
    I think you should use bcadd(0,$yournumber,2) it will give you perfect result. – jewelhuq May 31 '18 at 19:21
  • If value is 1.255 and then we convert it so we will get 1.26 but what can we do if we want to get value 1.25 from 1.255. please let me know any trick for this. – Bhavin Thummar Jul 02 '19 at 13:13
  • @BhavinThummar You can use round() with mode PHP_ROUND_HALF_DOWN, as show Somnath's answer. If you want to round down, and always maintain 2dp, then you could use a mixture of this answer, and Somnath's to round first, and then use number_format to make sure it is output in the correct way. – Codemwnci Jul 08 '19 at 11:49
  • if you want to avoid round up of values and keep number to 2 decimal places this will work fine `floor($number * 100) / 100;` – somsgod Jul 26 '19 at 09:27
  • Also please note that this method returns a **localised number**. That means 1234.567 will be outputted as '1,234.57'. In some cases you might not want a thousands separator. – finngu Feb 01 '23 at 10:23
  • @finngu: It's a parameter of that function, as shown in the answers example at the time of your comment: https://3v4l.org/0lAiH -- "20105.045" -> 20105.05; The third parameter of https://php.net/number_format ; `$thousands_separator` . – hakre Aug 27 '23 at 23:23
  • @hakre It is shown, but not explained. I just added some additional info, because others might miss it, just as I did in the beginning. Localised numbers can be an easy to overlook mistake. – finngu Aug 30 '23 at 07:44
372

Use round() (use if you are expecting a number in float format only, else use number_format() as an answer given by Codemwnci):

echo round(520.34345, 2);   // 520.34
echo round(520.3, 2);       // 520.3
echo round(520, 2);         // 520

From the manual:

Description:

float round(float $val [, int $precision = 0 [, int $mode = PHP_ROUND_HALF_UP ]]);

Returns the rounded value of val to specified precision (number of digits after the decimal point). precision can also be negative or zero (default).

...

Example #1 round() examples

<?php
    echo round(3.4);         // 3
    echo round(3.5);         // 4
    echo round(3.6);         // 4
    echo round(3.6, 0);      // 4
    echo round(1.95583, 2);  // 1.96
    echo round(1241757, -3); // 1242000
    echo round(5.045, 2);    // 5.05
    echo round(5.055, 2);    // 5.06
?>

Example #2 mode examples

<?php
    echo round(9.5, 0, PHP_ROUND_HALF_UP);   // 10
    echo round(9.5, 0, PHP_ROUND_HALF_DOWN); // 9
    echo round(9.5, 0, PHP_ROUND_HALF_EVEN); // 10
    echo round(9.5, 0, PHP_ROUND_HALF_ODD);  // 9

    echo round(8.5, 0, PHP_ROUND_HALF_UP);   // 9
    echo round(8.5, 0, PHP_ROUND_HALF_DOWN); // 8
    echo round(8.5, 0, PHP_ROUND_HALF_EVEN); // 8
    echo round(8.5, 0, PHP_ROUND_HALF_ODD);  // 9
?>
Jacopo Pace
  • 460
  • 7
  • 14
Somnath Muluk
  • 55,015
  • 38
  • 216
  • 226
236

Alternatively,

$padded = sprintf('%0.2f', $unpadded); // 520 -> 520.00
Marc B
  • 356,200
  • 43
  • 426
  • 500
  • 4
    So what if you want `520,00`? I guess the other answer works better in that case. – SPRBRN Apr 28 '14 at 13:55
  • 3
    ^no the other answer will not give two decimal places for an int – pythonian29033 Aug 19 '14 at 12:34
  • 2
    other reasons you may want this is you dont want rounding... or in my cause SQL floats returned are not treated the same as normal floats which is a PHP math bug – Amb3rL4nn Feb 22 '17 at 05:48
  • @SPRBRN - [number_format](https://www.php.net/manual/en/function.number-format.php) has an option to specify decimal separator character. – ToolmakerSteve Mar 03 '21 at 23:37
  • 1
    I tried this first but the output is converted to a string so you and I have to return it back to float again , so take care of this point – Ahmed Bermawy Jul 10 '23 at 11:34
56

http://php.net/manual/en/function.round.php

e.g.

echo round(5.045, 2);    // 5.05

echo round(5.055, 2);    // 5.06
aksu
  • 5,221
  • 5
  • 24
  • 39
SystemX17
  • 3,637
  • 4
  • 25
  • 36
  • Round will do the exact functionality that Rich is wanting, but number_format() would be more interesting to look into for all kinds of numerical formatting. – Shamim Hafiz - MSFT Dec 19 '10 at 15:15
  • This method will perform rounding as well over just forcing the digits ".00" on the end. – SystemX17 Dec 19 '10 at 15:15
  • 21
    I'd tried round, but it doesn't work - it won't add the extra .00. – Rich Bradshaw Dec 19 '10 at 15:18
  • Try using one of the examples I have there, it on it's own in a PHP script. You should get the commented result. If not then you have a problem with your PHP setup somewhere. – SystemX17 Dec 20 '10 at 02:13
  • 2
    round(520, 2) returns 520, not 520.00 as required by @Rich – user761100 Oct 15 '18 at 14:59
  • 2
    Update for PHP 7.4+ since this answer is very old. Since round returns a float it can only be guaranteed to return a number with at most one decimal place (ie, it returns something that is not an integer, with the minimum number of decimal places possible to represent the number). So `round(1,2)` (or any level or precision) returns '*1.0*', because '1.00' would not be a valid float. To make numbers behave like strings, you need to use string manipulation functions. (Previous versions of PHP may have acted differently/less logically) – fred2 Jul 14 '20 at 13:24
  • 1
    @fred2 - To convert float to a string with desired format, use `sprintf` or `number_format`. Internally, a float isn't `3.0`; its simply a binary value that is at (or sometimes very close to) 3. To convert to a string that has two decimal digits: `$str = sprintf("%0.2f", $value);` – ToolmakerSteve Mar 03 '21 at 23:54
  • 1
    Yeah, I know. That's why I said "To make numbers behave like strings, you need to use string manipulation functions". – fred2 Mar 05 '21 at 03:11
  • I was fighting with this as well until I realized this. I needed .00 output, basically money output. The float isn't actually money data type. In my opinion then, it makes sense to output the string value. For that I like answer from @Codemwnci best. – gregthegeek Feb 07 '23 at 23:17
33

Try:

$number = 1234545454; 
echo  $english_format_number = number_format($number, 2); 

The output will be:

1,234,545,454.00
Leigh
  • 28,765
  • 10
  • 55
  • 103
Biju
  • 339
  • 3
  • 2
26

Use the PHP number_format() function.

For example,

$num = 7234545423;
echo number_format($num, 2);

The output will be:

7,234,545,423.00
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sani Kamal
  • 1,208
  • 16
  • 26
20

You can use the PHP printf or sprintf functions:

Example with sprintf:

$num = 2.12;
echo sprintf("%.3f", $num);

You can run the same without echo as well. Example: sprintf("%.3f", $num);

Output:

2.120

Alternatively, with printf:

echo printf("%.2f", $num);

Output:

2.124
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Aditya P Bhatt
  • 21,431
  • 18
  • 85
  • 104
19

use round(yourValue,decimalPoint) (php manual’s page) or number_format(yourValue,decimalPoint);

number_format() return value as string like this type 1,234.67. so in this case you can not use it for addition or any calculation. if you try then you have to deal with Number Format Error...

In this case round(121222.299000000,2) will be better option. The result would be 121222.29 ...

Christian Bonato
  • 1,253
  • 11
  • 26
pankaj
  • 1
  • 17
  • 36
  • Hi @pankaj , I was wondering because using ```number_format()``` returns ```string``` how can I change it to 0.00 without being a string? Thank you – natsumiyu Feb 15 '23 at 00:53
  • @natsumiyu: number_format() is _for_ returning a string, if you need a floating point number use https://php.net/round , round() , which is _for_ returning a float. As written in the answer you requested feedback for in your comment, see first and last sentence, however mind comments like this one: https://stackoverflow.com/questions/4483540/show-a-number-to-two-decimal-places#comment4903201_4483553 – hakre Aug 27 '23 at 23:29
15

Another more exotic way to solve this issue is to use bcadd() with a dummy value for the $right_operand of 0.

$formatted_number = bcadd($number, 0, 2);
powtac
  • 40,542
  • 28
  • 115
  • 170
  • 3
    Note that `bc*` functions do not round up, they always round down. For example, `bcadd("1.0999","0.0",1)` yields "1.0", not "1.1". – ColinM Jul 18 '18 at 20:25
  • 3
    BC Math functions actually just stop processing at `$scale` fractional digits. This equals rounding towards zero. – Oktokolo Aug 22 '19 at 00:40
14

Here I get two decimals after the . (dot) using a function...

function truncate_number($number, $precision = 2) {

    // Zero causes issues, and no need to truncate
    if (0 == (int)$number) {
        return $number;
    }

    // Are we negative?
    $negative = $number / abs($number);

    // Cast the number to a positive to solve rounding
    $number = abs($number);

    // Calculate precision number for dividing / multiplying
    $precision = pow(10, $precision);

    // Run the math, re-applying the negative value to ensure
    // returns correctly negative / positive
    return floor( $number * $precision ) / $precision * $negative;
}

Results from the above function:

echo truncate_number(2.56789, 1); // 2.5
echo truncate_number(2.56789);    // 2.56
echo truncate_number(2.56789, 3); // 2.567

echo truncate_number(-2.56789, 1); // -2.5
echo truncate_number(-2.56789);    // -2.56
echo truncate_number(-2.56789, 3); // -2.567

New Correct Answer

Use the PHP native BC Math function bcdiv

echo bcdiv(2.56789, 1, 1);  // 2.5
echo bcdiv(2.56789, 1, 2);  // 2.56
echo bcdiv(2.56789, 1, 3);  // 2.567
echo bcdiv(-2.56789, 1, 1); // -2.5
echo bcdiv(-2.56789, 1, 2); // -2.56
echo bcdiv(-2.56789, 1, 3); // -2.567
hakre
  • 193,403
  • 52
  • 435
  • 836
Hardik Kalathiya
  • 2,221
  • 1
  • 18
  • 28
13
bcdiv($number, 1, 2) // 2 varies for digits after the decimal point

This will display exactly two digits after the decimal point.

Advantage:

If you want to display two digits after a float value only and not for int, then use this.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Wasim A.
  • 9,660
  • 22
  • 90
  • 120
  • 1
    This is the most universal solution if you have bcdiv (it's a stock but non-default package on centos6). – Shovas Nov 13 '18 at 15:26
10
$retailPrice = 5.989;
echo number_format(floor($retailPrice*100)/100,2, '.', ''); 

It will return 5.98 without rounding the number.

Pang
  • 9,564
  • 146
  • 81
  • 122
mrphpguru
  • 123
  • 1
  • 6
  • Only this can also do the job `floor($retailPrice * 100) / 100;` no need of number format then. – somsgod Jul 26 '19 at 09:29
10

Use the PHP number_format() function.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Shamim Hafiz - MSFT
  • 21,454
  • 43
  • 116
  • 176
8

I make my own.

$decimals = 2;
$number = 221.12345;
$number = $number * pow(10, $decimals);
$number = intval($number);
$number = $number / pow(10, $decimals);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
joanlgr
  • 99
  • 1
  • 4
  • 1
    Its nice to see some of the maths needed to do this. Although using a built in function is preferred for me. Theres no point re-inventing the wheel. – Lightbulb1 Dec 11 '13 at 14:43
  • 2
    Sorry, but round(), as it says, round de number, and sometimes, i do not want to round. – joanlgr Dec 20 '13 at 15:16
  • @joanlgr: 221.12345 you write in the example, but it's one of those numbers that don't exist for the computer and therefore some form of rounding - even you don't want it sometimes - already has been encoded by just writing this statement `$number = 221.12345` and letting PHP parse and execute it. Adding more lines of code afterwards does not change (but repeats) it. E.g. _"By definition, floating-point error cannot be eliminated, and, at best, can only be managed."_ from https://en.wikipedia.org/wiki/Floating-point_error_mitigation and the warning @ https://php.net/float. – hakre Aug 27 '23 at 23:49
8

For conditional rounding off ie. show decimal where it's really needed otherwise whole number

123.56 => 12.56

123.00 => 123

$somenumber = 123.56;

$somenumber = round($somenumber,2);

if($somenumber == intval($somenumber))
{
    $somenumber = intval($somenumber);
}

echo $somenumber; // 123.56


$somenumber = 123.00;

$somenumber = round($somenumber,2);

if($somenumber == intval($somenumber))
{
    $somenumber = intval($somenumber);
}

echo $somenumber; // 123    
Vinay
  • 7,442
  • 6
  • 25
  • 48
7

round_to_2dp is a user-defined function, and nothing can be done unless you posted the declaration of that function.

However, my guess is doing this: number_format($number, 2);

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ajreal
  • 46,720
  • 11
  • 89
  • 119
  • 18
    From your first paragraph, I think you've misunderstood the question. `round_to_2dp($number);` was meant as pseudocode; the OP was asking for somebody to tell him what to replace that expression with. – Mark Amery Nov 12 '13 at 16:23
6
$twoDecNum = sprintf('%0.2f', round($number, 2));

The rounding correctly rounds the number and the sprintf forces it to 2 decimal places if it happens to to be only 1 decimal place after rounding.

Tunaki
  • 132,869
  • 46
  • 340
  • 423
JohnS
  • 61
  • 1
  • 1
6

Adding to other answers, since number_format() will, by default, add thousands separator.

To remove this, do this:

$number = number_format($number, 2, ".", "");
Glorious Kale
  • 1,273
  • 15
  • 25
  • is there a way that it will not return string when using ```number_format()```? – natsumiyu Feb 15 '23 at 06:55
  • @natsumiyu: No, `number_format()` is _for_ returning a string, also in it's name: _format_. Use `round()` if you're looking for a floating point number. See as well https://php.net/float (_"Floating point numbers"_ in the PHP Manual). – hakre Aug 27 '23 at 23:38
5
$number = sprintf('%0.2f', $numbers); // 520.89898989 -> 520.89

This will give you 2 number after decimal.

Kampai
  • 22,848
  • 21
  • 95
  • 95
S'copion Sam
  • 69
  • 1
  • 2
  • 4
    No it won't. I don't know when this post was written but if you try it with your own example, at least on my machine :-) , it will output 520.90. Meaning, Rounding WILL occur. Be careful! – Boaz Rymland Mar 17 '16 at 13:25
5

If you want to use two decimal digits in your entire project, you can define:

bcscale(2);

Then the following function will produce your desired result:

$myvalue = 10.165445;
echo bcadd(0, $myvalue);
// result=10.11

But if you don't use the bcscale function, you need to write the code as follows to get your desired result.

$myvalue = 10.165445;
echo bcadd(0, $myvalue, 2);
// result=10.11

To know more

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
jewelhuq
  • 1,210
  • 15
  • 19
2

Number without round

$double = '21.188624';
echo intval($double) . '.' . substr(end(explode('.', $double)), 0, 2);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Abhishek Sharma
  • 300
  • 2
  • 7
0

Here's another solution with strtok and str_pad:

$num = 520.00
strtok(round($num, 2), '.') . '.' . str_pad(strtok('.'), 2, '0')
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Bryan
  • 3,449
  • 1
  • 19
  • 23
0
  • Choose the number of decimals
  • Format commas(,)
  • An option to trim trailing zeros

Once and for all!

function format_number($number,$dec=0,$trim=false){
  if($trim){
    $parts = explode(".",(round($number,$dec) * 1));
    $dec = isset($parts[1]) ? strlen($parts[1]) : 0;
  }
  $formatted = number_format($number,$dec); 
  return $formatted;
}

Examples

echo format_number(1234.5,2,true); //returns 1,234.5
echo format_number(1234.5,2);      //returns 1,234.50
echo format_number(1234.5);        //returns 1,235
Kareem
  • 5,068
  • 44
  • 38
  • 1
    Hi @Kareem , I was wondering how can I return the decimal format not being a string? I tried your code but the return is a string. Thank you – natsumiyu Feb 15 '23 at 01:01
  • Hi @natsumiyu, you can simply declare the variable type depending on your use case. If you always need a number to be return you can edit the function to declare (int) there on the returned string. *$num = (int) format_number(1234.5,2);* – Kareem Mar 10 '23 at 06:27
0

That's the same question I came across today and want to round a number and return float value up to a given decimal place and it must not be string (as returned from number_format) the answer is

printf('%.' . $decimalPlaces . 'f', round($number, $decimalPlaces));

thanks to mickmackusa for indicating the mistake

Rehan Anis
  • 788
  • 1
  • 5
  • 7
  • `echo sprintf()` is an antipattern. It is more sensibly written as `printf()` only. – mickmackusa May 05 '22 at 02:26
  • I tried to use this but I still get a string value. – natsumiyu Feb 15 '23 at 00:56
  • 1
    sprintf() will never return float value, so it's really hard to understand what you are trying to achieve. Either way, both round() and sprintf() are featured in the existing answers, so I don't find this one adding anything new. – Your Common Sense May 02 '23 at 13:50