note 106395 added to function.round

From: Date: Fri, 04 Nov 2011 16:02:00 +0000
Subject: note 106395 added to function.round
Groups: php.notes 
Request: Send a blank email to php-notes+get-184306@lists.php.net to get a copy of this message
Re-definition of round for early versions of php: <?php function roundhelper( $value, $mode) { $tmp_value=0.0; if ($value >= 0.0) { $tmp_value = floor($value + 0.5); if (($mode == "PHP_ROUND_HALF_DOWN" && $value == (-0.5 + $tmp_value))) { $tmp_value = $tmp_value - 1.0; } } else { $tmp_value = ceil($value - 0.5); if (($mode == "PHP_ROUND_HALF_DOWN" && $value == (0.5 + $tmp_value))) { $tmp_value = $tmp_value + 1.0; } } return $tmp_value; } function mathround( $value, $places, $mode) { $f1=0.0; $f2=0.0; $tmp_value=0.0; $precision_places=0; /*if (!php_math_is_finite($value)) { return $value; }*/ $precision_places = 14 - floor(log10(abs($value))); $f1 = pow(10, abs($places)); /* If the decimal precision guaranteed by FP arithmetic is higher than the requested $places BUT is small enough to make sure a non-zero $value is returned, pre-round the result to the precision */ if ($precision_places > $places && $precision_places - $places < 15) { $f2 = pow(10, abs($precision_places)); if ($precision_places >= 0) { $tmp_value = $value * $f2; } else { $tmp_value = $value / $f2; } /* preround the result (tmp_$value will always be something * 1e14, thus never larger than 1e15 here) */ $tmp_value = roundhelper($tmp_value, $mode); /* now correctly move the decimal point */ $f2 = pow(10, abs($places - $precision_places)); /* because $places < $precision_places */ $tmp_value = $tmp_value / $f2; } else { /* adjust the value */ if ($places >= 0) { $tmp_value = $value * $f1; } else { $tmp_value = $value / $f1; } /* This $value is beyond our precision, so rounding it is pointless */ if (abs($tmp_value) >= 1e15) { return $value; } } /* round the temp value */ $tmp_value = roundhelper($tmp_value, $mode); /* see if it makes sense to use simple division to round the value */ if (abs($places) < 23) { if ($places > 0) { $tmp_value = $tmp_value / $f1; } else { $tmp_value = $tmp_value * $f1; } } else { /* Simple division can't be used since that will cause wrong results. Instead, the number is converted to a string and back again using strtod(). strtod() will return the nearest possible FP value for that string. */ /* 40 Bytes should be more than enough for this format string. The float won't be larger than 1e15 anyway. But just in case, use snprintf() and make sure the buffer is zero-terminated */ //char buf[40]; snprintf($buf, 39, "%15fe%d", $tmp_value, -$places); $buf[39] = '\0'; //tmp_value = zend_strtod(buf, NULL); /* couldn't convert to string and back */ /*if (!zend_finite(tmp_value) || zend_isnan(tmp_value)) { tmp_value = value; }*/ } return $tmp_value; } $numero=number_format("1254.50",2,'.',''); echo "Valor: " . mathround($numero , 0, "PHP_ROUND_HALF_DOWN") ."\n"; //SHOW 1254 $numero=number_format("1254.51",2,'.',''); echo "Valor: " . mathround($numero , 0, "PHP_ROUND_HALF_DOWN") ."\n"; //SHOW 1255 ?> ---- Server IP: 190.2.55.64 Probable Submitter: 190.247.131.151 ---- Manual Page -- http://www.php.net/manual/en/function.round.php Edit -- https://master.php.net/note/edit/106395 Del: integrated -- https://master.php.net/note/delete/106395/integrated Del: useless -- https://master.php.net/note/delete/106395/useless Del: bad code -- https://master.php.net/note/delete/106395/bad+code Del: spam -- https://master.php.net/note/delete/106395/spam Del: non-english -- https://master.php.net/note/delete/106395/non-english Del: in docs -- https://master.php.net/note/delete/106395/in+docs Del: other reasons-- https://master.php.net/note/delete/106395 Reject -- https://master.php.net/note/reject/106395 Search -- https://master.php.net/manage/user-notes.php

« previous php.notes (#184306) next »