I want to drop off decimals without rounding up. For example if I have 1.505, I want to drop last decimal and value should be 1.50. Is there such a function in PHP?
13 Answers
You need floor() in this way:
$rounded = floor($float*100)/100;
Or you cast to integer:
$rounded = 0.01 * (int)($float*100);
This way it will not be rounding up.
-
Works fine unless the trailing 0 in the example is a requirement. – Leigh Jan 31 '12 at 12:13
-
1For negative values, use ceil() instead of floor() – Boaz Rymland Mar 17 '16 at 15:11
-
1this is not a complete solution UNLESS you _only_ have positive numbers - you need to use BOTH `floor()` and `ceil()` if you don't know the sign of the number you are rounding - see [this answer](http://stackoverflow.com/a/28821326/3092596) – goredwards Apr 26 '16 at 16:49
-
1This is not an absolutely correct solution. `floor(5.1*100)/100;` yields `5.09`, instead of expected `5.10`. You can try with 5.100, or 4.1 the same incorrect result. – Muhammed Jan 05 '17 at 18:53
-
Like @MuhammedM. said, it doesn't work accurately all the time, like this case: `floor(19.99 * 100)` returns `1998` instead of `1999`. This should not be the correct answer – evilReiko Apr 10 '18 at 12:31
-
It didn't worked correctly for say example input: 2581.68. It returns "2581.67", however expected return value is "2581.68". – Prince Bhanwra Nov 13 '19 at 23:22
-
You can use my solution with preg_replace to avoid all of the issues above. It just treats it like a string, cuts it and puts it back as a number. See answer further down. – Watts Epherson Jan 22 '20 at 10:25
-
Use intval() rather than floor(). – Misunderstood Jul 04 '20 at 14:40
-
2Perfect. Used it to get 2 digit and applied number_format with 2 to properly show my price. Thanks – dipak_pusti Mar 18 '21 at 03:08
-
`bcdiv()` does require the [https://www.php.net/manual/en/book.bc.php](BCMath) PHP extension. Most PHP versions have it enabled by default. To check if your PHP has it enabled, look for "BCMath support => enabled" in the output of `phpinfo()` or `$ php -i | grep BCMath` – John Kary Apr 06 '21 at 16:27
To do this accurately for both +ve and -ve numbers you need use:
- the php floor()
function for +ve numbers
- the php ceil()
function for -ve numbers
function truncate_float($number, $decimals) {
$power = pow(10, $decimals);
if($number > 0){
return floor($number * $power) / $power;
} else {
return ceil($number * $power) / $power;
}
}
the reason for this is that floor()
always rounds the number down, not towards zero.
ie floor()
effectively rounds -ve numbers towards a larger absolute value
eg floor(1.5) = 1
while floor(-1.5) = -2
Therefore, for the multiply by power, remove decimals, divide by power
truncate method :
- floor()
only works for positive numbers
- ceil()
only works for negative numbers
To test this, copy the following code into the editor of http://phpfiddle.org/lite (or similar):
<div>Php Truncate Function</div>
<br>
<?php
function truncate_float($number, $places) {
$power = pow(10, $places);
if($number > 0){
return floor($number * $power) / $power;
} else {
return ceil($number * $power) / $power;
}
}
// demo
$lat = 52.4884;
$lng = -1.88651;
$lat_tr = truncate_float($lat, 3);
$lng_tr = truncate_float($lng, 3);
echo 'lat = ' . $lat . '<br>';
echo 'lat truncated = ' . $lat_tr . '<br>';
echo 'lat = ' . $lng . '<br>';
echo 'lat truncated = ' . $lng_tr . '<br><br>';
// demo of floor() on negatives
echo 'floor (1.5) = ' . floor(1.5) . '<br>';
echo 'floor (-1.5) = ' . floor(-1.5) . '<br>';
?>

- 2,486
- 2
- 30
- 40
$float = 1.505;
echo sprintf("%.2f", $float);
//outputs 1.50

- 2,490
- 18
- 20
-
Works beautifully when combined with typecasting `(float) $float` if you're continuing to use this in calculations. – Jamie Dexter Jun 11 '13 at 16:20
-
11It's important to note that `sprintf` will ROUND floats if it thinks it needs to. For example, take the division `31 / 53 = 0.584905[...]` - if we want 3 decimal places, we can do `sprintf("%.3f", (31 / 53))` but this does NOT give us 0.584. It gives us 0.585. – Jamie Dexter Jun 13 '13 at 14:43
-
5
-
1It is expected without rounding... 5.555 should be 5.55 not. 5.56 – Umakant Patil Sep 03 '15 at 08:02
-
3
-
Also, `echo sprintf()` is an "antipattern". There is absolutely no reason that anyone should ever write `echo sprintf()` in any code for any reason -- it should be `printf()` every time. This answer is not lying, however, that it provides the desired result from the sample input: https://3v4l.org/PQoKW Jamie is not wrong either -- https://3v4l.org/h37XV and Loenix is correct as well https://3v4l.org/SsNUb . So it seems this technique is not reliable. – mickmackusa Apr 08 '22 at 09:40
Maybe it's too late, but here's a good approach:
$getTruncatedValue = function( $value, $precision )
{
//Casts provided value
$value = ( string )$value;
//Gets pattern matches
preg_match( "/(-+)?\d+(\.\d{1,".$precision."})?/" , $value, $matches );
//Returns the full pattern match
return $matches[0];
};
var_dump
(
$getTruncatedValue(1.123,1), //string(3) "1.1"
$getTruncatedValue(1.345,2), //string(4) "1.34"
$getTruncatedValue(1.678,3), //string(5) "1.678"
$getTruncatedValue(1.90123,4) //string(6) "1.9012"
);
- The only pitfall in this approach may be the need to use a Regular Expression (which sometimes could bring a performance penalty).
Note: It's quite hard to find a native approach to truncate decimals, and I think it's not possible to perform that using sprintf and other string-related functions.

- 39
- 3
-
1
-
This should be the accepted answer, I come to this solution also and this approach prevent any form of rounding data – vincent PHILIPPE Oct 29 '21 at 13:21
The answers of RenaPot, IsisCode, goredwards are not correct.
Because of how float works in computers (in general), float is not accurate.
To replicate the issue:
floor(19.99 * 100); // Outputs 1998 instead of 1999
floor( 5.10 * 100); // Outputs 509 instead of 510
Within PHP internally, 19.99 * 100
results in something like 1998.999999999999999
, which when we do floor
of that, we get 1998
.
Solution:
Solution 1: Use bcmath library (Suggested by @SamyMassoud) if you have it installed (some shared hosting servers may not have it installed by default). Like so:
//floor(19.99 * 100);// Original
floor(bcmul(19.99, 100));// Outputs 1999
Solution 2: String manipulation (my recommendation):
// Works with positive and negative numbers, and integers and floats and strings
function withoutRounding($number, $total_decimals) {
$number = (string)$number;
if($number === '') {
$number = '0';
}
if(strpos($number, '.') === false) {
$number .= '.';
}
$number_arr = explode('.', $number);
$decimals = substr($number_arr[1], 0, $total_decimals);
if($decimals === false) {
$decimals = '0';
}
$return = '';
if($total_decimals == 0) {
$return = $number_arr[0];
} else {
if(strlen($decimals) < $total_decimals) {
$decimals = str_pad($decimals, $total_decimals, '0', STR_PAD_RIGHT);
}
$return = $number_arr[0] . '.' . $decimals;
}
return $return;
}
// How to use:
withoutRounding(19.99, 2);// Return "19.99"
withoutRounding(1.505, 2);// Return "1.50"
withoutRounding(5.1, 2);// Return "5.10"

- 65
- 1
- 5

- 19,501
- 24
- 86
- 102
We can use bc functions if they are available:
echo bcadd(sprintf('%F', 5.445), '0', 2); // => 5.44
echo sprintf('%.2F', 5.445); // => 5.45

- 127
- 5
you can convert 1.505
to String data type and make use of substring()
to truncate last character.
And again convert it in integer
.

- 1,528
- 17
- 41
$num = 118.74999669307;
$cut = substr($num, 0, ((strpos($num, '.')+1)+2));`
// Cut the string from first character to a length of 2 past the decimal.
/ substr(cut what, start, ( (find position of decimal)+decimal itself)+spaces after decimal) )
echo $cut;
this will help you shorten the float value without rounding it..

- 124
- 1
- 5
-
Its taken me quite a while to find this answer, it looks very promising as the solution! – Tom Sep 09 '18 at 20:07
-
but what happens if you don't know how long the decimal is and what happens if you have this scenario: 1.3E+10 – Danny F Jul 15 '21 at 14:27
Its easy and work better.
$value = 12.9987876;
$value_exp = explode(".", $value);
$value_new = floatval($value_exp[0].'.'.substr($value_exp[1],0,4));
echo $value_new; // output will 12.9987

- 11
- 3
I know this is a late answer but here is a simple solution. Using the OP example of 1.505 you can simply use the following to get to 1.50.
function truncateExtraDecimals($val, $precision) {
$pow = pow(10, $precision);
$precise = (int)($val * $pow);
return (float)($precise / $pow);
}
This manages both positive and negative values without the concern to filter which function to use and lends to correct results without the worry about what other functions might do with the value.
$val = 1.509;
$truncated = sprintf('%.2f', truncateExtraDecimals($val, 2));
echo "Result: {$truncated}";
Result: 1.50
The sprintf is needed to get exactly 2 decimals to display otherwise the Result would have been 1.5 instead of 1.50.

- 3
- 2
To avoid using ceil, floor and round, just treat it as a string and cut it if necessary. This avoids all the rounding issues.
The code below looks for the first 2 numbers after the dot and singles them out. Then it looks for any numbers that trail that. It then replaces the entire thing with only the 2 numbers it found. If number doesn't match the replace rule, nothing changes.
You could stick this in a function call and pass the function the number and the quantity of numbers you want to keep after the decimal place.
// Shorten number to 2 decimal places without rounding
$num = 2213.145;
$num = floatval(preg_replace("/\.([0-9]{2})[0-9]{0,99}/",".$1",$num));

- 692
- 5
- 9
-
This might be a good solution if you want to drop off all the decimals. – evilReiko Apr 11 '18 at 13:18