Bug #70173 [Com]: Precision problem in float

From: Date: Sat, 08 Aug 2015 12:41:55 +0000
Subject: Bug #70173 [Com]: Precision problem in float
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-195022@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=70173&edit=1

 ID:                 70173
 Comment by:         rainer dot jung at kippdata dot de
 Reported by:        rainer dot jung at kippdata dot de
 Summary:            Precision problem in float
 Status:             Open
 Type:               Bug
 Package:            *General Issues
 Operating System:   Solaris 10 Sparc
 PHP Version:        7.0.0beta2
 Block user comment: N
 Private report:     N

 New Comment:

Concerning zend_strtod():

- I first tried the original library available under www.netlib.org/fp. It didn't show the
problem.

- I then tried to shrink the delta between the PHP copy and the original and ended up with a test
case, that doesn't show the problem even with PHP zend_strtod(). So it seems it is something in
PHP before the calls to zend_strtod(), or the problem is in the output rendering of the float.

Here's my test:

1) Create a file dtoa-main.c containing:

#include <stdio.h>
#include <zend_strtod.h>

int main() {
    fprintf(stdout, "%f\n", zend_strtod("29000000", NULL));
    fprintf(stdout, "%f\n", zend_strtod("290000000", NULL));
    fprintf(stdout, "%f\n", zend_strtod("2900000000", NULL));
    fprintf(stdout, "%f\n", zend_strtod("29000000000", NULL));
    fprintf(stdout, "%f\n", zend_strtod("290000000000", NULL));
    fprintf(stdout, "%f\n", zend_strtod("2900000000000", NULL));
    fprintf(stdout, "%f\n", zend_strtod("29000000000000", NULL));
    fprintf(stdout, "%f\n", zend_strtod("290000000000000", NULL));
    fprintf(stdout, "%f\n", zend_strtod("2900000000000000", NULL));
}

The numbers are the same as in the test.php I originally use to produce the problem.

Now compile this snippet against the original zend_strtod.o object file:

solaris10.sparc apache% gcc -I /path/to/php/bldir/Zend -I /path/to/php/bldir/TSRM -I
/path/to/php/bldir -Wl,-z -Wl,nodefs -o dtoa-test dtoa-main.c
/path/to/php/bldir/Zend/.libs/zend_strtod.o

The "-z nodefs" linker argument is only needed, because the object file references the
zend_error_noreturn symbol, which is not used in this test case. I didn't want to soak in many
more object files.

Now run the binary:

./dtoa-test
29000000.000000
290000000.000000
2900000000.000000
29000000000.000000
290000000000.000000
2900000000000.000000
29000000000000.000000
290000000000000.000000
2900000000000000.000000

So the float seems to be OK.


Previous Comments:
------------------------------------------------------------------------
[2015-08-08 11:06:44] rainer dot jung at kippdata dot de

Problem still exists for 7.0.0 Beta 3.

Linux x86_64 builds are fine (as expected).

------------------------------------------------------------------------
[2015-08-03 13:06:41] cmb@php.net

That might be related to the update of Zend/zend_strtod*[1].

[1] <https://github.com/php/php-src/commit/5d4616e2b08f20ce6a582587cf9d3e34775a43a4>

------------------------------------------------------------------------
[2015-07-31 05:53:27] rainer dot jung at kippdata dot de

Description:
------------
A precision problem in float makes a huge number of tests fail. It could well be, that this is a
platform specific failure (Solaris 10 Sparc, 32 Bit build).

Below you will find a test case with correct result returned from version 5.6.11 and wrong result
from 7.0.0 Beta 2.


Test script:
---------------
<?php
$var = 29000000;
var_dump($var);
$var = 290000000;
var_dump($var);
$var = 2900000000;
var_dump($var);
$var = 29000000000;
var_dump($var);
$var = 290000000000;
var_dump($var);
$var = 2900000000000;
var_dump($var);
$var = 29000000000000;
var_dump($var);
$var = 290000000000000;
var_dump($var);
$var = 2900000000000000;
var_dump($var);
?>

Expected result:
----------------
int(29000000)
int(290000000)
float(2900000000)
float(29000000000)
float(290000000000)
float(2900000000000)
float(29000000000000)
float(2.9E+14)
float(2.9E+15)


Actual result:
--------------
int(29000000)
int(290000000)
float(2899998720)
float(28999991296)
float(289999945728)
float(2899998408704)
float(28999988281344)
float(2.899999499223E+14)
float(2.8999984254812E+15)



------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=70173&edit=1


Thread (16 messages)

« previous php.bugs (#195022) next »