Delete digits after two decimal points, without rounding the value

PhpFunctionRounding

Php Problem Overview


i have value in php variable like that

$var='2.500000550';
echo $var

what i want is to delete all decimal points after 2 digits.

like now value of variable will be

$var='2.50';
echo $var

> keep in mind this value is coming from mysql databse

but when i use round php function i got round but i dont need round, i just need to delete all digits after 2 decimal simple.

i have tired, flot() and lot of other option no success.

Thanks

Php Solutions


Solution 1 - Php

TL;DR:

The PHP native function bcdiv seems to do precisely what is required, and properly.

To simply "truncate" a number, bcdiv($var, 1, 2); where 2 is the number of decimals to preserve (and 1 is the denomenator - dividing the number by 1 allows you to simply truncate the original number to the desired decimal places)

Full Answer (for history)

This turns out to be more elusive than one might think.

After this answer was (incorrectly) upvoted quite a bit, it has come to my attention that even sprintf will round.

Rather than delete this answer, I'm turning it into a more robust explanation / discussion of each proposed solution.

number_format - Incorrect. (rounds)
Try using number format:

$var = number_format($var, 2, '.', '');  // Last two parameters are optional
echo $var;
// Outputs 2.50

If you want it to be a number, then simply type-cast to a float:

$var = (float)number_format($var, 2, '.', '');

Note: as has been pointed out in the comments, this does in fact round the number.

sprintf - incorrect. (sprintf also rounds)
If not rounding the number is important, then per the answer below, use sprintf:

$var = sprintf("%01.2f", $var);

floor - not quite! (floor rounds negative numbers)

floor, with some math, will come close to doing what you want:

floor(2.56789 * 100) / 100; // 2.56

Where 100 represents the precision you want. If you wanted it to three digits, then:

floor(2.56789 * 1000) / 1000; // 2.567

However, this has a problem with negative numbers. Negative numbers still get rounded, rather than truncated:

floor(-2.56789 * 100) / 100; // -2.57

"Old" Correct answer: function utilizing floor

So a fully robust solution requires 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 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

Solution 2 - Php

floor(2.500000550 * 100) / 100;

This should do your task...

Solution 3 - Php

You're requesting a function that returns "2.50" and not 2.5, so you aren't talking about arithmetic here but string manipulation. Then preg_replace is your friend:

$truncatedVar = preg_replace('/\.(\d{2}).*/', '.$1', $var);

// "2.500000050" -> "2.50", "2.509" -> "2.50", "-2.509" -> "2.50", "2.5" -> "2.5"

If you want to do it with arithmetic, simply use:

$truncatedVar = round($var * 100) / 100);

// "2.500000050" -> "2.5", "2.599" -> "2.59", "-2.599" -> "2.59"

Solution 4 - Php

try with number_format:

echo number_format('2.50000050', 2); // 2.50

Solution 5 - Php

number_format rounds the number

php > echo number_format(128.20512820513, 2)."\n";
128.21

I used preg_replace to really cut the string

php > echo preg_replace('/(\.\d\d).*/', '$1', 128.20512820513)."\n";
128.20

Solution 6 - Php

someone posted here about

> floor(2.500000550 * 100) / 100;

function cutAfterDot($number, $afterDot = 2){
$a = $number * pow(10, $afterDot);
$b = floor($a);
$c = pow(10, $afterDot);
echo "a $a, b $b, c $c<br/>";
return $b/$c ;
}
echo cutAfterDot(2.05,2);

a 205, b 204, c 100
2.04

so in raw form don't use it... But if you add a little epsilon...

function cutAfterDot($number, $afterDot = 2){
		return floor($number * pow(10, $afterDot) + 0.00001) / pow(10, $afterDot);
	}

it works!

Solution 7 - Php

Use the PHP native function bcdiv.

Example:

echo bcdiv(3.22871, 1, 1);  // 3.2
echo bcdiv(3.22871, 1, 2);  // 3.22
echo bcdiv(3.22871, 1, 3);  // 3.228
echo bcdiv(-3.22871, 1, 1); // -3.2
echo bcdiv(-3.22871, 1, 2); // -3.22

For your case:

$var='2.500000550';
echo $var
echo bcdiv($var, 1, 2);  // 2.50

Solution 8 - Php

Solution 9 - Php

The following is (what I believe is - please correct me if not) a robust mathematical* solution, based mostly on the information from several other answerers here, and a small amount from me

(*Which is not to suggest there's anything wrong with Liphtier's regex-based answer - just that I can see purists wanting to avoid regex for what is arguably a mathematical problem.)

  • sprintf(), number_format() (and round(), obviously), are all performing a rounding operation so are not appropriate for the non-rounding truncation requested in the question (not on their own, at least).
  • In lieu of an out-of-the-box function, the seemingly most elegant solution was Sujit Agarwal's answer
  • But because of the way floats are stored, we need to use an epsilon - as pointed out in David Constantine's answer (where he also makes the previous solution more general by using pow() to get the right factor based on a specified precision).
  • But then, as pointed out in cale_b's answer, any use of floor() (or presumably ceil()) may produce unintended results for negatives without use of abs().
  • And the value I'm trying to add is:
  • If using a division on abs() to get a negation factor, we need to account for the special case when the input is 0.
  • We should dynamically create the epsilon; A static hard-coded epsilon might be too small or too large, depending on the precision required. I haven't seen this issue addressed in the other answers.

The code I'm using is:

public static function truncate_decimal($number, $leavePlaces = 2)
{
	if ($number == 0) return 0;
	$negate = $number / abs($number);
	$shiftFactor = pow(10, $leavePlaces);
	$epsilon = pow(10, -1 * $leavePlaces);
	return floor(abs($number) * $shiftFactor + $epsilon) / $shiftFactor * $negate;
}

Solution 10 - Php

Already a lot of possible solutions, I just want to add the one that I came up to solve my problem.

function truncate_decimals($number, $decimals=2)
{
  $factor = pow(10,$decimals); 
  $val = intval($number*$factor)/$factor;
  return $val;
}


truncate_decimals(199.9349,2);
// 199.93

Solution 11 - Php

All of the solutions which use number_format are wrong because number_format performs rounding.

The function below should work on all numbers, you can specify the decimal separator for those countries which use ','.

function truncate_decimal($number, $truncate_decimal_length = 2, $decimal_character = '.', $thousands_character = '') {

$number = explode($decimal_character, $number);
$number[1] = substr($number[1], 0, $truncate_decimal_length);
$number_truncated = implode($decimal_character, $number);
return number_format($number_truncated, $truncate_decimal_length, $decimal_character, $thousands_character);

}

Solution 12 - Php

A simple function to follow would be "If greater than 0 floor, else ceil", using a multiplier to raise it above the decimal point temporarily whilst doing it:

function trim_num($num_in, $dec_places = 2) {
	$multiplier = pow(10, $dec_places); // 10, 100, 1000, etc
	if ($num_in > 0) {
		$num_out = floor($num_in * $multiplier) / $multiplier;
	} else {
		$num_out = ceil($num_in * $multiplier) / $multiplier;
	}
	return $num_out;
}

Solution 13 - Php

$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; 

Solution 14 - Php

> floor - not quite! (floor rounds negative numbers)

A possible solution from cale_b answer.

static public function rateFloor($rate, $decimals)
{

    $div = "1" . str_repeat("0", $decimals);

    if ($rate > 0) {
        return floor($rate * $div) / $div;
    }

    $return = floor(abs($rate) * $div) / $div;

    return -($return);

}

static public function rateCeil($rate, $decimals)
{

    $div = "1" . str_repeat("0", $decimals);

    if ($rate > 0) {
        return ceil($rate * $div) / $div;
    }

    $return = ceil(abs($rate) * $div) / $div;

    return -($return);

}

Positive

> Rate: 0.00302471 > > Floor: 0.00302400 > > Ceil: 0.00302500

Negative

> Rate: -0.00302471 > > Floor: -0.00302400 > > Ceil: -0.00302500

Solution 15 - Php

If you don't want to round the number but you want to remove the decimal places you can use "substr" method

substr(string, start, length);
substr(4.96, 0, -1);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionairView Question on Stackoverflow
Solution 1 - Phprandom_user_nameView Answer on Stackoverflow
Solution 2 - PhpSujit AgarwalView Answer on Stackoverflow
Solution 3 - PhpfluView Answer on Stackoverflow
Solution 4 - PhpmatinoView Answer on Stackoverflow
Solution 5 - PhpLiphtierView Answer on Stackoverflow
Solution 6 - PhpDavid ConstantineView Answer on Stackoverflow
Solution 7 - PhpFaisalView Answer on Stackoverflow
Solution 8 - PhpAurimas LičkusView Answer on Stackoverflow
Solution 9 - PhpSepsterView Answer on Stackoverflow
Solution 10 - PhpvictoryoalliView Answer on Stackoverflow
Solution 11 - PhpleexonlineView Answer on Stackoverflow
Solution 12 - PhpDavid BellView Answer on Stackoverflow
Solution 13 - PhpSujjad AView Answer on Stackoverflow
Solution 14 - PhpJon C.View Answer on Stackoverflow
Solution 15 - PhpFahad AhmedView Answer on Stackoverflow