When BcMath\Number
was introduced it allowed string|int
method
arguments. According to a separate RFC to allow int
to the functions
this was done as a performance optimization. Unfortunately this also
means it effectively disallows float
types because PHP will truncate
them to integers (and emit a deprecation report) instead of preserving
them as strings.
Example: https://3v4l.org/Bi5Kl
var_dump(
(string)new BcMath\Number(5)->sub(4.2, 1),
bcsub(5, 4.2, 1),
);
string(3) "1.0"
string(3) "0.8"
Per SakiTakamachi:
If there is strong demand for creating the object from a
float
, it
would be better to add support forfloat
rather than removingint
from the signature.
As with the bc functions, converting afloat
to astring
can be
easily handled within php-src.In any case, discussion on the mailing list is necessary.
I was hoping to be able to use Number as a drop-in replacement for
various operations, especially back-of-the-napkin calculations, but this
behavior makes it too easy to accidentally write $number * 1.2
and get
unexpected results.
There are many arguments that could be made that float is the wrong
type, that it has rounding issues, and possibly other edge cases, but in
the vast majority of cases (string)$float
does exactly what is
expected. The lack of a non-float decimal numeric type doesn't leave
much room for native expression short of doing Number((string)$i) * Number((string)$j)
or Number('1.2') * '1.2'
.
The expectation is that in PHP 9.0 float-to-int will be disallowed and
would automatically drop back to float-to-string in this case, but that
is still a long way away and would mean being unable to recommend using
Number in 8.4, 8.5, and beyond.
Request context and discussion:
https://github.com/php/php-src/issues/18674
BcMath\Number RFC:
https://wiki.php.net/rfc/support_object_type_in_bcmath
bcmath function int type RFC:
https://wiki.php.net/rfc/allow_int_args_to_bcmath_function
When
BcMath\Number
was introduced it allowedstring|int
method arguments. According to a separate RFC to allowint
to the functions this was done as a performance optimization. Unfortunately this also means it effectively disallowsfloat
types because PHP will truncate them to integers (and emit a deprecation report) instead of preserving them as strings.Example: https://3v4l.org/Bi5Kl
var_dump( (string)new BcMath\Number(5)->sub(4.2, 1), bcsub(5, 4.2, 1), ); string(3) "1.0" string(3) "0.8"
Per SakiTakamachi:
If there is strong demand for creating the object from a
float
, it would be better to add support forfloat
rather than removingint
from the signature.
As with the bc functions, converting afloat
to astring
can be easily handled within php-src.In any case, discussion on the mailing list is necessary.
I was hoping to be able to use Number as a drop-in replacement for various operations, especially back-of-the-napkin calculations, but this behavior makes it too easy to accidentally write
$number * 1.2
and get unexpected results.There are many arguments that could be made that float is the wrong type, that it has rounding issues, and possibly other edge cases, but in the vast majority of cases
(string)$float
does exactly what is expected. The lack of a non-float decimal numeric type doesn't leave much room for native expression short of doingNumber((string)$i) * Number((string)$j)
orNumber('1.2') * '1.2'
.The expectation is that in PHP 9.0 float-to-int will be disallowed and would automatically drop back to float-to-string in this case, but that is still a long way away and would mean being unable to recommend using Number in 8.4, 8.5, and beyond.
Request context and discussion:
https://github.com/php/php-src/issues/18674BcMath\Number RFC:
https://wiki.php.net/rfc/support_object_type_in_bcmathbcmath function int type RFC:
https://wiki.php.net/rfc/allow_int_args_to_bcmath_function
Hi Russell!
As I already mentioned in the issue thread, I want to clarify just in case: even if we allow float
as an argument, the internal behavior would essentially be the same as passing (string) $float_num
.
In fact, implementing any kind of custom conversion logic should be avoided, as it could lead to inconsistencies with PHP’s native casting behavior.
Also, even if implicit casting behavior changes in PHP 9.0, please note that this would not benefit methods when strict_types=1
.
Personally, I chose not to accept float
in the method signature because I prioritize the precision of BCMath.
To be honest, I’m curious about how much demand there actually is for this kind of feature.
Regards,
Saki