note 92920 deleted from function.bcscale by danbrown

From: Date: Fri, 14 Aug 2009 19:43:09 +0000
Subject: note 92920 deleted from function.bcscale by danbrown
References: 1  Groups: php.notes 
Request: Send a blank email to php-notes+get-159491@lists.php.net to get a copy of this message
Note Submitter: francois dot barbier at gmail dot com ---- The function provided by "mwgamera at gmail dot com" (http://www.php.net/function.bcscale#79628) 2 comments below doesn't work well with negative numbers. Example: <?php bcscale(3); var_dump(round(-1, 2)); // float(-1) var_dump(bcround('-1', 2)); // string(5) "-0.99" => incorrect $a = bcdiv('-1', '3'); var_dump(round($a, 2)); // float(-0.33) var_dump(bcround($a, 2)); // string(5) "-0.32" => incorrect $a = bcdiv('-2', '3'); var_dump(round($a, 2)); // float(-0.67) var_dump(bcround($a, 2)); // string(5) "-0.66" => incorrect ?> Here is a modified version that works correctly: <?php /** * Round an arbitrary precision number * * @param string $sNumber The value to round. * @param int $iPrecision The optional number of decimal digits to round * to, defaults to 0. * @return string The rounded value. */ function bcround($sNumber, $iPrecision = 0) { $iPrecision = (int) $iPrecision; $sZeros = str_repeat('0', abs($iPrecision)); if (0 > $iPrecision) { return bcmul(bcround(bcdiv($sNumber, '1'.$sZeros, 1)), '1'.$sZeros, 0); } else { $sSign = ''; if ('-' === substr($sNumber, 0, 1)) { $sSign = '-'; } return bcadd($sNumber, $sSign.'0.'.$sZeros.'5', $iPrecision); } } ?> Example: <?php bcscale(3); var_dump(round(-1, 2)); // float(-1) var_dump(bcround('-1', 2)); // string(5) "-1.00" => correct $a = bcdiv('-1', '3'); var_dump(round($a, 2)); // float(-0.33) var_dump(bcround($a, 2)); // string(5) "-0.33" => correct $b = bcdiv('-2', '3'); var_dump(round($b, 2)); // float(-0.67) var_dump(bcround($b, 2)); // string(5) "-0.67" => correct ?> Like the round() function, it also accepts negative precision: <?php $a = '123456'; var_dump(round($a, -2)); // float(123500); var_dump(bcround($a, -2)); // string(6) "123500"; $a = '-123456'; var_dump(round($a, -2)); // float(-123500); var_dump(bcround($a, -2)); // string(6) "-123500"; ?> Bonus: below is a function that does what "Nitrogen" (http://www.php.net/function.bcscale#88463) did 1 comment below: <?php /** * Strip trailing zeros of an arbitrary precision number * * @param string $sNumber The value to trim. * @param string The modified value. */ function bctrim($sNumber) { $iPosition = strpos($sNumber, '.'); if (FALSE === $iPosition) { return $sNumber; } else { return substr($sNumber, 0, $iPosition). rtrim(substr($sNumber, $iPosition), '.0'); } } ?> Example: <?php var_dump(bctrim('1000')); // string() "1000" var_dump(bctrim('1000.0000')); // string() "1000" var_dump(bctrim('1000.1000')); // string() "1000.1" var_dump(bctrim('1000.0001')); // string() "1000.0001" ?>

« previous php.notes (#159491) next »