rfc:precise_float_value

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revision Both sides next revision
rfc:precise_float_value [2015/09/25 00:05]
yohgaki
rfc:precise_float_value [2016/06/05 19:02]
bukka Update voting choice
Line 1: Line 1:
 ====== PHP RFC: More precise float value handling ====== ====== PHP RFC: More precise float value handling ======
-  * Version: 0.9+  * Version: 1.1
   * Date: 2015-07-30   * Date: 2015-07-30
-  * Author: Yasuo Ohgaki <yohgaki@ohgaki.net>+  * Author: Yasuo Ohgaki <yohgaki@ohgaki.net>, Jakub Zelenka <bukka@php.net>
   * Status: Under Discussion   * Status: Under Discussion
   * First Published at: http://wiki.php.net/rfc/precise_float_value   * First Published at: http://wiki.php.net/rfc/precise_float_value
Line 8: Line 8:
 ===== Introduction ===== ===== Introduction =====
  
-This RFC is based on float like JSON numeric discussion and proposes more precise float value handling overall.+This RFC is based on the discussion about displaying float values in json_encode and proposes more precise float value handling overall.
  
-JSON is used to exchange data between systems. Although [[https://tools.ietf.org/html/rfc7159|JSON RFC "6 Numbers"]]  does not require specific implementation for float/int type, float value should be able to handle precise float values as much as possible by default. +JSON is used to exchange data between systems. Although [[https://tools.ietf.org/html/rfc7159|JSON RFC "6 Numbers"]]  does not require specific implementation for float/int type, float value should be handled as precise as possible by default. 
  
-Currently, json_encode() uses EG(precision) which is 14. IEEE 754 double supports more precision and serialize()/var_export() uses PG(serialize_precision)=17 to be more precise. Since json_encode() uses EG(precision), json_encode() removes lower digits of fraction parts and destroys original value even if PHP's float could hold more precise float value. +Currently, json_encode() uses EG(precision) which is set to 14. That means that 14 digits max are used for displaying (printing) the number. IEEE 754 double supports higher precision and serialize()/var_export() uses PG(serialize_precision)=17 to be more precise. Since json_encode() uses EG(precision), json_encode() removes lower digits of fraction parts and destroys original value even if PHP's float could hold more precise float value.
  
 <code php> <code php>
Line 40: Line 40:
 </code> </code>
  
-PHP's float type stores "raw" IEEE 754 double and could store accurate fraction value up 17 digits.+PHP's float type stores "raw" IEEE 754 double and could display accurate fraction value up to 17 digits.
  
 Current PHP outputs meaningless values for oversized EG(precision)/PG(serialize_precision). Current PHP outputs meaningless values for oversized EG(precision)/PG(serialize_precision).
Line 57: Line 57:
 float(0.12345678901234567736988623209981597028672695159912109375) float(0.12345678901234567736988623209981597028672695159912109375)
 </code> </code>
 +
 +That is caused by used mode for double to string conversion.
  
 ===== Proposal ===== ===== Proposal =====
  
-  * PHP 7.1: Introduce EG(precision)=-1 and PG(serialize_precision)=-1 that uses zend_dtoa()'s 0 mode that rounds to nearest value. (-1 is used to indicate 0 mode+This RFC proposes to introduce EG(precision)=-1 and PG(serialize_precision)=-1 that uses zend_dtoa()'mode which uses better algorigthm for rounding float numbers (-1 is used to indicate 0 mode).
- +
-Since JSON is used extensively for web apps, we may have JSON specific INI setting for better compatibility and ease of use. +
- +
-  * PHP 7.1: Add JSON_G(json_precision) - Add JSON module specific precision INI setting. +
- +
-PHP 5.6/7.0's json_encode() uses EG(precision) and could lose floating point number information.  +
- +
-  * PHP 5.6/7.0: Make json_encode() uses PG(serialize_precision).+
  
 +The RFC also proposes changing ini for JSON precision to PG(serialize_precision).
  
 Followings are sample codes and outputs of the proposed patch. Followings are sample codes and outputs of the proposed patch.
Line 80: Line 75:
 ini_set('precision', -1); ini_set('precision', -1);
 ini_set('serialize_precision', -1); ini_set('serialize_precision', -1);
-ini_set('json.precision', -1); 
  
 var_dump($v); var_dump($v);
Line 103: Line 97:
 ini_set('precision', 14); ini_set('precision', 14);
 ini_set('serialize_precision', 17); ini_set('serialize_precision', 17);
-ini_set('json.precision', 14); 
  
 var_dump($v); var_dump($v);
 echo var_export($v, true), PHP_EOL; echo var_export($v, true), PHP_EOL;
 +ini_set('serialize_precision', 14);
 echo json_encode($v), PHP_EOL; echo json_encode($v), PHP_EOL;
 +ini_set('serialize_precision', 17);
 echo $v, PHP_EOL; echo $v, PHP_EOL;
 ?> ?>
Line 123: Line 118:
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
  
-PHP 7.0 will have 0 mode as the defaultvar_export()/serialize() may have different number+Setting mode as default can mean that the rounding will be more precise which also means that the rounding might be different in var_export()/serialize().
  
-FYI: Existing tests passes even when 0 mode is used.+The BC break could happen only if someone would rely on exact output but that shouldn't be the case. All our existing tests passes when 0 mode is used.
  
 None when old INI value is used. None when old INI value is used.
Line 131: Line 126:
 ===== Proposed PHP Version(s) ===== ===== Proposed PHP Version(s) =====
  
-  * PHP 7.1.0 - EG(precision)/PG(serialize_precision) 0 mode and JSON_G(json_precision) that support 0 mode. +  * PHP 7.1
-  * PHP 5.6.x/7.0.0 - JSON uses PG(serialize_precision) for float precision.+
  
 ===== RFC Impact ===== ===== RFC Impact =====
Line 142: Line 136:
   * 0 mode (EG(precision)= -1) float outputs values rounded to nearest.   * 0 mode (EG(precision)= -1) float outputs values rounded to nearest.
  
-Standard module +Standard module and JSON 
-  * serialize(), var_export() - PHP7.1: Use PG(serialieze_precision) and 0 mode. +  * serialize(), var_export()json_encode - Use PG(serialize_precision) and 0 mode by default.
- +
-JSON +
-  * json_encode() PHP7.1: Use PG(serialize_precision) and 0 mode. PHP5.6/7.0: Use PG(serialize_precision).  It uses EG(precision) currently. If JSON_G(json_precision) is accepted, use it instead of PG(serialize_precision). +
  
 ==== To Opcache ==== ==== To Opcache ====
Line 164: Line 154:
   * php.ini-production values : 14 Unmodified   * php.ini-production values : 14 Unmodified
  
-serialize_precision(PHP5.6) +serialize_precision
-  * hardcoded default values : 17 Unmodified +
-  * php.ini-development values : 17 Unmodified +
-  * php.ini-production values : 17 Unmodified +
- +
-serialize_precision(PHP7) +
-  * hardcoded default values : -1 +
-  * php.ini-development values : -1 +
-  * php.ini-production values : -1 +
- +
-json_precision(NEW - PHP7 only)+
   * hardcoded default values : -1   * hardcoded default values : -1
   * php.ini-development values : -1   * php.ini-development values : -1
Line 190: Line 170:
  
 ===== Future Scope ===== ===== Future Scope =====
- 
-  * Remove PG(serialize_precision) setting. If we are going to remove PG(serialize_precision) in the future, we may be better to have JSON_G(json_precision) as one may need specific precision for JSON data. 
  
 WDDX WDDX
Line 202: Line 180:
 ===== Proposed Voting Choices ===== ===== Proposed Voting Choices =====
  
-Requires a 50%+1 majority+Requires a 2/3 majority
  
-Please choose Yes/No for 0 mode EG(precision)/PG(serialize_precision)+There will be two votings
  
-<doodle title="Introduce mode to EG(precision)/PG(serialize_precision) for PHP 7.1" auth="yohgaki" voteType="single" closed="True"> +  * whether to introduce mode and use it as default for serialize_precision 
-   * Yes +  * should PG(serialize_precision) be used instead of EG(precision) in json_encode.
-   * No +
-</doodle>+
  
-.+===== Patches and Tests =====
  
-Please choose your preference whether JSON module should use PG(serialize_precision) or new JSON_G(json_precision). i.e. JSON module has its own precision setting or not.+The initial PR can be found here:
  
-<doodle title="Add JSON_G(json_precision) for JSON module only setting for PHP 7.1" auth="yohgaki" voteType="single" closed="True"> +  * https://github.com/php/php-src/pull/1455
-   * Yes +
-   * No +
-</doodle>+
  
-+Note that the PR is currently outdate but it will be updated if the RFC is accepted.
- +
-Please choose if PHP 5.6's JSON should use PG(serialize_precision) or EG(precision). Currently it uses EG(precision). +
- +
-<doodle title="Make json_encode() uses PG(serialize_precision) for PHP 5.6" auth="yohgaki" voteType="single" closed="True"> +
-   * Yes +
-   * No +
-</doodle> +
- +
-Please choose if PHP 7.0's JSON should use PG(serialize_precision) or EG(precision). Currently it uses EG(precision). +
- +
-<doodle title="Make json_encode() uses PG(serialize_precision) for PHP 7.0" auth="yohgaki" voteType="single" closed="True"> +
-   * Yes +
-   * No +
-</doodle> +
- +
- +
- +
-===== Patches and Tests ===== +
- +
-  * https://github.com/php/php-src/pull/1455+
  
 ===== Implementation ===== ===== Implementation =====
Line 250: Line 203:
 ===== References ===== ===== References =====
  
-https://marc.info/?l=php-internals&m=143786181229714&w=2+  * https://marc.info/?l=php-internals&m=143786181229714&w=2 
 +  * https://bugs.php.net/bug.php?id=71473 
 +  * http://blog.reverberate.org/2016/02/06/floating-point-demystified-part2.html
  
 ===== Rejected Features ===== ===== Rejected Features =====
 Keep this updated with features that were discussed on the mail lists. Keep this updated with features that were discussed on the mail lists.
  
rfc/precise_float_value.txt · Last modified: 2017/09/22 13:28 (external edit)