ID: 24876 User updated by: jeff at tmtrading dot com Reported By: jeff at tmtrading dot com -Status: Bogus +Status: Open Bug Type: Math related Operating System: Redhat 8.0 PHP Version: 4CVS-2003-07-30 (stable) New Comment:
I am going to assue you are testing on windows instead of linux as I specified. I downloaded the latest stable snapshot this morning, but this time I also downloaded the windows version. Windows returns the correct result, RedHat linux 8.0 does not. The linux (and perhaps other unicies) math libraries return different numbers than windows does. Thus, if you look at other libraries or math applications which manipulate double's, they always include some amount of "fuzz". I realize that you guys are trying to go through bugs as quickly as possible, and weeding out the "bogus" ones can be daunting, but please don't close bugs until you have properly reproduced the potential problem. Previous Comments: ------------------------------------------------------------------------ [2003-07-30 22:16:27] [EMAIL PROTECTED] Round works fine, 4.045 rounded to 2 digits == 4.05. Not bug. ------------------------------------------------------------------------ [2003-07-30 19:12:04] jeff at tmtrading dot com 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); ------------------------------------------------------------------------ [2003-07-30 18:57:44] 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: ---------------- [EMAIL PROTECTED] 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: -------------- [EMAIL PROTECTED] 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 ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/?id=24876&edit=1