Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No Truncate function in PHP - Options?

I have an algorithm that performs the following calculations:

  1. ( ( 0.50 * 0 ) + 7 ) / 10 = 0.70
  2. ( ( 0.70 * 10 ) + 9 ) / 20 = 0.80
  3. ( ( 0.80 * 20 ) + 7 ) / 30 = 0.7666666667 -> I want this value to truncate to 0.76

So that it may feed into the rest of the calculation as:

4a. ( ( 0.76 * 30 ) + 8 ) / 40 = 0.77

And not to feed in when rounded up two decimal places as 0.77:

4b. ( ( 0.77 * 30 ) + 8 ) / 40 = 0.77

****The following seem to have failed and instead force a round up to 0.77:****

The PHP sptrinf() function: PHP dropping decimals without rounding up

The PHP number_format() function: PHP: show a number to 2 decimal places

The PHP floor() function: Truncate float numbers with PHP

  • Is there another way?
  • Is it at all possible to achieve what I want (truncate to two decimal places) with PHP?

Please assist. Many thanks.

UPDATE - SOLVED Ok, it is working now thanks to dkamins and zneak. I used the floor() approach (I assume I wasn't doing something right in the past). However, now the following happens:

e.g.

(0.86 * 30) + 9 ) / 40 = 0.87 (it should), yet after TRUNC it = 0.86

How is it truncating 0.87 to 0.86? It makes no sense. Is there a way to get it to truncate only if there are more than 2 decimal places?

SOLVED:

$numDecPlace = strlen(substr(strrchr($newRel, "."), 1));
echo '<p>Test: Number of decimal places=' .$numDecPlace. '</p>';
if($numDecPlace > 2) {
    $newRel = floor($newRel * 100) / 100; // Truncate to 2dp.
    echo '<p>Test: New relationship truncated is $newRel=' .$newRel. '</p>';
}
like image 454
leokennedy Avatar asked May 17 '12 20:05

leokennedy


4 Answers

All the answers given here round the number. This function worked for me and i hope for you too.

function truncate($number, $decimals)
{
  $point_index = strrpos($number, '.'); 
  return substr($number, 0, $point_index + $decimals+ 1);
}

Where $number is the number to truncate and$decimals is the number of decimals you want. Example: truncate(-38.59540719940386 , 6); returns -38.595407

If you want, check substr's documentation!

like image 199
Fernando Prieto Avatar answered Nov 17 '22 02:11

Fernando Prieto


You can use PHP's floor function along with some decimal shifting like so:

floor(0.7666666667 * 100) / 100;
like image 4
dkamins Avatar answered Nov 17 '22 03:11

dkamins


how about round()

  <?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
  ?>
like image 2
Sunil Kartikey Avatar answered Nov 17 '22 02:11

Sunil Kartikey


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 truncate method using multiply by power, round, then divide by power:
- 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>';
?>
like image 1
goredwards Avatar answered Nov 17 '22 02:11

goredwards