php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #64760 var_export() does not use full precision for floating-point numbers
Submitted: 2013-05-02 12:12 UTC Modified: 2013-11-19 22:03 UTC
From: cf0hay at gmail dot com Assigned: yohgaki (profile)
Status: Closed Package: Variables related
PHP Version: 5.4.14 OS: Linux 64bit (PHP 64bit too)
Private report: No CVE-ID: None
 [2013-05-02 12:12 UTC] cf0hay at gmail dot com
Description:
------------
var_export() truncates floating-point precision. serialize() does not have the same problem.

Test script:
---------------
<?php
$a = microtime(true);

echo "error of serialize(): ";
var_export($a - unserialize(serialize($a))); //This returns 0.
echo "\n";

echo "error of var_export(): ";
eval('$b = '.var_export($a,true).';');
var_export($a - $b); //Almost never 0.
echo "\n";


Expected result:
----------------
Exporting a floating-point value should generate enough digits to prevent precision loss. The script above should always return 0 on the second case.

Actual result:
--------------
The difference between the original floating point value and the one exported differs. The error is about 15 magnitude lower than the magnitude of the value itself.

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2013-10-23 09:09 UTC] yohgaki@php.net
-Status: Open +Status: Analyzed
 [2013-10-23 09:09 UTC] yohgaki@php.net
The difference came from 

var_export()
-------------------------------------------------------
	case IS_DOUBLE:
		tmp_len = spprintf(&tmp_str, 0,"%.*H", (int) EG(precision), Z_DVAL_PP(struc));
		smart_str_appendl(buf, tmp_str, tmp_len);
		efree(tmp_str);
		break;-------------------------------------------------------



serialize()
-------------------------------------------------------
		case IS_DOUBLE: {
				char *s;

				smart_str_appendl(buf, "d:", 2);
				s = (char *) safe_emalloc(PG(serialize_precision), 1, MAX_LENGTH_OF_DOUBLE + 1);
				php_gcvt(Z_DVAL_P(struc), PG(serialize_precision), '.', 'E', s);
				smart_str_appends(buf, s);
				smart_str_appendc(buf, ';');
				efree(s);
				return;
			}
-------------------------------------------------------

var_export() uses precision=14 while serialize() uses precision=17 by default.

-------
[yohgaki@dev php-5.5]$ php -e precision=17 scr.php
error of serialize(): 0
error of var_export(): 0
-------

Since var_export() is better to behave like serialize(), var_export() is better to use PG(serialize_precision) instead of PG(precision).
 [2013-10-23 23:53 UTC] yohgaki@php.net
-Assigned To: +Assigned To: yohgaki
 [2013-10-29 11:29 UTC] yohgaki@php.net
-Status: Analyzed +Status: Closed
 [2013-10-29 11:29 UTC] yohgaki@php.net
Committed fix, but not auto closed. Closing

 3cf2682083fc1c8635b02c4cf77bdf12c5e5da35
 [2013-11-14 03:07 UTC] whatthejeff@php.net
This change can break tests on some systems. See https://github.com/php/php-src/pull/525.
 [2013-11-14 03:09 UTC] whatthejeff@php.net
Corrected link: https://github.com/php/php-src/pull/525
 [2013-11-14 03:13 UTC] whatthejeff@php.net
This might also be worth mentioning in the UPGRADING file and/or the documentation as it caused some confusion in the PHPUnit project: https://github.com/sebastianbergmann/phpunit/issues/1052
 [2013-11-19 22:03 UTC] yohgaki@php.net
I've mentioned in NEWS that this bug was fixed in 5.4/5.5.

I can understand your proposal, but UPGRADING is for new release..
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 12:01:29 2024 UTC