-
Notifications
You must be signed in to change notification settings - Fork 7.9k
number_format: float within range of int can be cast to int … #12333
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…unding to not loose precision
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks sensible to me, might need an upgrading entry
According to Wikipedia numbers above 2^52 can't have fractions anymore:
If that's true we could also improve precision for even more cases. |
Updated to 2^52 now. Also a quick benchmark: <?php
$number = 4503599627370496.0;
$iterations = 100000;
$start = hrtime(true);
for ($i = 0; $i < $iterations; $i += 1) {
$tmp = number_format($number);
}
$end = hrtime(true);
$spend = $end - $start;
printf('%s iterations: %Fs (%Fns per run)', $iterations, $spend / 1000000000, $spend / $iterations); Before: |
(Z_DVAL_P(num) >= 4503599627370496.0 || Z_DVAL_P(num) <= -4503599627370496.0) | ||
&& ZEND_DOUBLE_FITS_LONG(Z_DVAL_P(num)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't ZEND_DOUBLE_FITS_LONG(Z_DVAL_P(num))
a little bit faster than the first condition? We have the difference of one execution of Z_DVAL_P
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so.
- This is first checking the unusual case for numbers above 2^52
ZEND_DOUBLE_FITS_LONG
will castZEND_LONG_[MIN|MAX]
and compare double values as well!((d) >= (double)ZEND_LONG_MAX || (d) < (double)ZEND_LONG_MIN)
Z_DVAL_P(num)
results in*num.value.dval
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For number outside the order doesn't matter because two conditions must be met. But for number inside the range the second condition has only one Z_DVAL_P
evaluation and first condition has two of them. The comparison of doubles occurs in both conditions.
However, I think that the difference is so small that you can ignore my comment. Probably even it may be optimized by compiler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks reasonable to me. I will leave it open for another month to see if there are any comments and if not, I think we can merge it.
@bukka Can this be merged now? |
…before rounding of numbers above 2^52 to not loose precision.
On casting float to int fractional digits gets truncated but as far as I'm aware of
double
numbers above 2^52 can't store fractions anymore.This is the diff of the added test numbers without this change: