|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2003-07-30 18:57 UTC] jeff at tmtrading dot com
Description:
------------
php: php4-STABLE-200307301930
gcc: 3.2 20020903 (Red Hat Linux 8.0 3.2-7)
I tried to model the "myround" function after the c code.
I am not a C coder but I managed to get php to output the correct result with the following _hack_.
--- php/ext/standard/math.c 2003-01-16 07:08:59.000000000 -0700
+++ php/ext/standard/math.c 2003-07-30 16:23:44.000000000 -0700
@@ -114,6 +114,7 @@
zval **value, **precision;
int places = 0;
double f, return_val;
+ float fixme_val;
if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 2 ||
zend_get_parameters_ex(ZEND_NUM_ARGS(), &value, &precision) == FAILURE) {
@@ -142,10 +143,11 @@
f = pow(10.0, (double) places);
return_val *= f;
+ fixme_val = (float) return_val;
if (return_val >= 0.0)
- return_val = floor(return_val + 0.5);
+ return_val = floor((double)(fixme_val + 0.5));
else
- return_val = ceil(return_val - 0.5);
+ return_val = ceil((double)(fixme_val - 0.5));
return_val /= f;
RETURN_DOUBLE(return_val);
As you can see the patch is lame. Since I am not a C programmer I do not know how to figure out why this works vs. the original (it appears correct!).
Reproduce code:
---------------
$numbers = array(4.045, 5.055, 41.045, 51.055);
foreach($numbers as $number) {
printf("%f : %f : %f\n",$number, round($number,2), myround($number,2));
}
function myround($value, $precision) {
(int) $places = $precision;
(double) $f;
(double) $return_val = (double) $value;
$f = pow(10.0, (double) $places);
$return_val *= $f;
if($return_val >= 0.0)
$return_val = floor($return_val + 0.5);
else
$return_val = ceil($return_val - 0.5);
$return_val /= $f;
return $return_val;
}
Expected result:
----------------
[jclark@deadeye cli]$ ./php -n -f test.php
4.045000 : 4.050000 : 4.050000
5.055000 : 5.060000 : 5.060000
41.045000 : 41.050000 : 41.050000
51.055000 : 51.060000 : 51.060000
Actual result:
--------------
[jclark@deadeye cli]$ ./php -n -f ./test.php
4.045000 : 4.040000 : 4.050000
5.055000 : 5.050000 : 5.060000
41.045000 : 41.050000 : 41.050000
51.055000 : 51.050000 : 51.060000
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Wed Oct 22 23:00:01 2025 UTC |
Actually, below would seem to be a better solution. What I'm trying to point out is that writing a round function in php and the php's standard funtion give two different answers. That is just plain wrong. There's probably a better way to fix it, but the patch below works for me (limited testing). --- php4-STABLE-200307151930/ext/standard/math.c 2003-01-16 07:08:59.000000000 -0700 +++ php4-STABLE-200307301930/ext/standard/math.c 2003-07-30 17:04:50.000000000 -0700 @@ -114,6 +114,7 @@ zval **value, **precision; int places = 0; double f, return_val; + double fuzz = 0.01; if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 2 || zend_get_parameters_ex(ZEND_NUM_ARGS(), &value, &precision) == FAILURE) { @@ -143,9 +144,9 @@ return_val *= f; if (return_val >= 0.0) - return_val = floor(return_val + 0.5); + return_val = floor((return_val + fuzz) + 0.5); else - return_val = ceil(return_val - 0.5); + return_val = ceil((return_val - fuzz) - 0.5); return_val /= f; RETURN_DOUBLE(return_val);I tested with Linux. Perhaps you could see the 'problem' better if you adjusted the precision ini setting. (e.g. ini_set('precision', 32); as first line in your script..)