Closed GusGold closed 6 years ago
Casting to string works as long as the number isn't too big or the fraction too small:
var_dump((string)90.05); // string(5) "90.05"
Unfortunately, it's pretty easy to get into scientific notation:
var_dump((string)9012908310238012.11) // string(18) "9.012908310238E+15"
var_dump((string)0.000021) // string(6) "2.1E-5"
It could work to check for "E+" or "E-" in the string and fall back to the number_format
method:
$strValue = (string)$fltValue;
if (preg_match("/E[\+\-]\d+$/", $strValue)) {
$strValue = number_format($fltValue, $scale, '.', '');
}
INF
and NAN
are already covered elsewhere in fromFloat()
so I have not considered them here.
Here's the 3v4l with my experiment: http://3v4l.org/0aVdK
@GusGold you can use something like Decimal::fromString("90.05");
.
fromFloat
exists because sometimes we have to start with native float numbers. By the way, the precision error isn't because the conversion, but because a native float number can't exactly represent the 90.05 number, so it isn't php-bignumbers fault. (ok, if $scale
is small we can have precision loss, but that's not the real problem).
In addition, the explanation of @shabbyrobe also holds.
EDIT: I've seen that @shabbyrobe proposes a solution to better cast "easy numbers" (not too big, not too small) , maybe it's possible to do a simple cast to string and call fromString. This evening I'll play with this to see if we can obtain better results.
When using number_format() like here, you are relying on php's float precision.
Trying to use a number like
Decimal::fromFloat(90.05)
will cause a precision error asnumber_format(90.05, 16, ".", "") === "90.0499999999999972"
.There needs to be another method used to load in the numbers initially, as all following operation are going to be wrong.