rfc:integer-rounding

Differences

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

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:integer-rounding [2024/02/25 16:52] – introduce force_float argument maberfc:integer-rounding [2024/04/02 07:07] (current) – Declined mabe
Line 1: Line 1:
 ====== PHP RFC: Rounding Integers as int ====== ====== PHP RFC: Rounding Integers as int ======
-  * Version: 0.1+  * Version: 0.2
   * Date: 2023-09-26   * Date: 2023-09-26
   * Author: Marc Bennewitz, php@mabe.berlin   * Author: Marc Bennewitz, php@mabe.berlin
-  * Status: Under Discussion+  * Status: Declined
   * First Published at: https://wiki.php.net/RFC/integer-rounding   * First Published at: https://wiki.php.net/RFC/integer-rounding
  
Line 13: Line 13:
 Except ''number_format'' all of these functions take a ''float|int'', do a cast to ''float'', process on floating point number only and finally return a '' float''. Except ''number_format'' all of these functions take a ''float|int'', do a cast to ''float'', process on floating point number only and finally return a '' float''.
  
-As a result of ''round'', ''ceil'' and ''floor'' you get a floating point number rounded to your needs.+As a result of ''round'', ''ceil'' and ''floor'' the resulting value will be a floating point number rounded to your needs.
  
 In most cases this is sufficient but in cases of handling integer values above 2^53 you start to end up with unexpected results due to floating point arithmetic and precision loss. In most cases this is sufficient but in cases of handling integer values above 2^53 you start to end up with unexpected results due to floating point arithmetic and precision loss.
  
-''number_format'' on the other hand produces human readable numbers as ''string'' and since PHP 8.3 it also performs rounding integers without casting it to floating point numbers to fix the above issues mentioned.+''number_format'' on the other hand produces human readable numbers as ''string'' and since PHP 8.3 it also performs rounding integers without casting it to floating point numbers to fix the above issue mentioned.
  
  
 ===== Proposal ===== ===== Proposal =====
  
-This RFC proposes to perform rounding on given int and return the resulting int if possible by default. +This RFC proposes to perform rounding on given int and return a rounded int value if possible by default. 
-In case of integer under-/overflow the value will be casted to a float (double) and rounded based on the floating point number as it's done currently.+In case of integer under-/overflow the value will be cast to a float (double) and rounded based on the floating point number as it's done currently.
  
 For ''ceil'', ''floor'' and ''round'' with ''precision >= 0'' this means a given int gets returned as is. For ''ceil'', ''floor'' and ''round'' with ''precision >= 0'' this means a given int gets returned as is.
 +----
 +Rounding a given float will perform rounding on floating point number directly and return float as it's done currently.
 +There will be no implicit cast to int because floats (double) can represent a much wider range of numbers than int (32 or 64 bit).
  
-An additional argument will be introduced `bool force_float`+Floating point numbers on the other hand gets imprecise on representing numbers > 2^53 but passing a float to be rounded such imprecision must be known in first place already. 
-In PHP 8.this will default to `force_float=trueto keep current behavior but the new behavior can already be used by passing `force_float=false`+---- 
-In PHP 9.0 the default will change to `force_float=true` to get the new behavior by default but the previous behavior can be forced with `force_float=true`.+An additional argument will be introduced ''bool force_float''
 +In PHP 8.next this will default to ''force_float=true'' to keep current behavior but the new behavior can already be used by passing ''force_float=false''
 +In PHP 9.0 the default will change to ''force_float=false'' to get the new behavior by default but the previous behavior can be forced with ''force_float=true''.
  
  
Line 43: Line 48:
  
 // rounding integers with force_float=false will process and return int if possible // rounding integers with force_float=false will process and return int if possible
-// else with force_float=true it will process on int but cast the result to float to keep previous behavior 
 ceil(int, force_float=false): int ceil(int, force_float=false): int
 ceil(int, force_float=true): float ceil(int, force_float=true): float
Line 51: Line 55:
 round(int, precision: < 0, force_float=false): int|float // implicit cast to float only in case of integer under-/overflow round(int, precision: < 0, force_float=false): int|float // implicit cast to float only in case of integer under-/overflow
 round(int, force_float=true): float round(int, force_float=true): float
- 
 </code> </code>
  
Line 58: Line 61:
 The ''int''-type is compatible to ''float'', returning an int instead of a float will still be a number accepted for type-hints of ''int'', ''float'', ''int|float'' or ''mixed'' with strict_types enabled. The ''int''-type is compatible to ''float'', returning an int instead of a float will still be a number accepted for type-hints of ''int'', ''float'', ''int|float'' or ''mixed'' with strict_types enabled.
  
-As a result PHP will behave more precise on rounding integer values.+As a result PHP will behave more precisely on rounding integer values.
  
  
Line 70: Line 73:
 var_dump(round(987654321098765432, precision: -3)); var_dump(round(987654321098765432, precision: -3));
 var_dump(round(987654321098765432, precision: -4)); // integer overflow var_dump(round(987654321098765432, precision: -4)); // integer overflow
 +var_dump(round(10000000000000055296)); // input is float
 var_dump(takeFloat(round(987654321098765432, precision: -3))); var_dump(takeFloat(round(987654321098765432, precision: -3)));
 var_dump(returnFloat(round(987654321098765432, precision: -3))); var_dump(returnFloat(round(987654321098765432, precision: -3)));
 +
 +echo "\n#########################\n";
 +
 +var_dump(round(1, force_float=true));
 +var_dump(round(1.0, force_float=true));
 +var_dump(round(987654321098765432, precision: -3, force_float=true));
 +var_dump(round(987654321098765432, precision: -4, force_float=true)); // integer overflow
 +var_dump(round(10000000000000055296, force_float=true)); // input is float
 +var_dump(takeFloat(round(987654321098765432, precision: -3, force_float=true)));
 +var_dump(returnFloat(round(987654321098765432, precision: -3, force_float=true)));
 +
 +echo "\n#########################\n";
 +
 +var_dump(round(1, force_float=false));
 +var_dump(round(1.0, force_float=false));
 +var_dump(round(987654321098765432, precision: -3, force_float=false));
 +var_dump(round(987654321098765432, precision: -4, force_float=false)); // integer overflow
 +var_dump(round(10000000000000055296, force_float=false)); // input is float
 +var_dump(takeFloat(round(987654321098765432, precision: -3, force_float=false)));
 +var_dump(returnFloat(round(987654321098765432, precision: -3, force_float=false)));
 </code> </code>
  
Line 80: Line 104:
 float(9.87654321098766E+17) float(9.87654321098766E+17)
 float(9.8765432109877E+17) float(9.8765432109877E+17)
 +float(1.0000000000000055E+19)
 float(9.87654321098766E+17) float(9.87654321098766E+17)
 float(9.87654321098766E+17) float(9.87654321098766E+17)
 +#########################
 +Unknown named parameter $force_float
 </code> </code>
  
-8.4 behavior:+8.4 behavior (no change by default but possible to opt-in to new behavior):
 <code> <code>
 float(1) float(1)
Line 90: Line 117:
 float(9.87654321098766E+17) float(9.87654321098766E+17)
 float(9.8765432109877E+17) float(9.8765432109877E+17)
 +float(1.0000000000000055E+19)
 +float(9.87654321098766E+17)
 +float(9.87654321098766E+17)
 +#########################
 +float(1)
 +float(1)
 +float(9.87654321098766E+17)
 +float(9.8765432109877E+17)
 +float(1.0000000000000055E+19)
 +float(9.87654321098766E+17)
 +float(9.87654321098766E+17)
 +#########################
 +int(1)
 +float(1)
 +int(987654321098765000)
 +float(9.8765432109877E+17)
 +float(1.0000000000000055E+19)
 float(9.87654321098766E+17) float(9.87654321098766E+17)
 float(9.87654321098766E+17) float(9.87654321098766E+17)
Line 100: Line 144:
 int(987654321098765000) int(987654321098765000)
 float(9.8765432109877E+17) float(9.8765432109877E+17)
 +float(1.0000000000000055E+19)
 +float(9.87654321098766E+17)
 +float(9.87654321098766E+17)
 +#########################
 +float(1)
 +float(1)
 +float(9.87654321098766E+17)
 +float(9.8765432109877E+17)
 +float(1.0000000000000055E+19)
 +float(9.87654321098766E+17)
 +float(9.87654321098766E+17)
 +#########################
 +int(1)
 +float(1)
 +int(987654321098765000)
 +float(9.8765432109877E+17)
 +float(1.0000000000000055E+19)
 float(9.87654321098766E+17) float(9.87654321098766E+17)
 float(9.87654321098766E+17) float(9.87654321098766E+17)
Line 112: Line 173:
  
 ===== Proposed PHP Version(s) ===== ===== Proposed PHP Version(s) =====
-  * Introduce new argument `force_float=truein PHP 8.next +  * Introduce new argument ''force_float=true'' in PHP 8.next 
-  * Change default to `force_float=falseas described in PHP 9.+  * Change default to ''force_float=false'' as described in PHP 9.
  
 ===== RFC Impact ===== ===== RFC Impact =====
Line 135: Line 196:
  
 ===== Unaffected PHP Functionality ===== ===== Unaffected PHP Functionality =====
-Rounding floating point numbers will not be effected in any way.+Rounding floating point numbers will not be affected in any way.
  
 ===== Future Scope ===== ===== Future Scope =====
-After PHP 9 it can be considered to deprecate and remove the `force_floatargument again but due to very long future this is not part of this RFC.+After PHP 9 it can be considered to deprecate and remove the ''force_float'' argument again but due to very long future this is not part of this RFC.
  
  
-===== Proposed Voting Choices ===== +===== Proposed Voting Choices =====  
-One primary vote (requires 2/3 majority): Round on int and return int+As per the voting RFC a yes/no vote with a 2/3 majority is needed for this proposal to be accepted. 
 +Voting started on 2024-03-17 and will end on 2024-04-02 00:00 GMT. 
 +<doodle title="Rounding Integers as int" auth="Marc Bennewitz" voteType="single" closed="false" closeon="2024-04-02T00:00:00Z"> 
 +   * Yes 
 +   * No 
 +</doodle>
  
 ===== Patches and Tests ===== ===== Patches and Tests =====
rfc/integer-rounding.1708879969.txt.gz · Last modified: 2024/02/25 16:52 by mabe