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

Reply via email to