How to check if double value is larger or smaller then PHP_INT_MAX
:
<?php
$result = (double)PHP_INT_MAX;
$result += 100.0;
if ($result > PHP_INT_MAX) {
echo "result is > then PHP_INT_MAX";
} else {
echo "result is <= then PHP_INT_MAX";
}
And the output is:
result is <= then PHP_INT_MAX
which is incorrect.
Then I tried with:
<?php
$result = (double)PHP_INT_MAX;
$result += 100.0;
//$result -= 100.0;
if ((int) $result < 0) {
echo "Solution 1: result is > then PHP_INT_MAX\n";
} else {
echo "Solution 1: result is <= then PHP_INT_MAX\n";
}
if (!filter_var(
$result,
FILTER_VALIDATE_INT,
array(
'options' => array(
'min_range' => 0,
'max_range' => PHP_INT_MAX,
)
)
)) {
echo "Solution 2: result is > then PHP_INT_MAX\n";
} else {
echo "Solution 2: result is <= then PHP_INT_MAX\n";
}
And it seemed to work:
Solution 1: result is > then PHP_INT_MAX
Solution 2: result is > then PHP_INT_MAX
But then I did this (decrease $result
for 100
):
<?php
$result = (double)PHP_INT_MAX;
//$result += 100.0;
$result -= 100.0;
if ((int) $result < 0) {
echo "Solution 1: result is > then PHP_INT_MAX\n";
} else {
echo "Solution 1: result is <= then PHP_INT_MAX\n";
}
if (!filter_var(
$result,
FILTER_VALIDATE_INT,
array(
'options' => array(
'min_range' => 0,
'max_range' => PHP_INT_MAX,
)
)
)) {
echo "Solution 2: result is > then PHP_INT_MAX\n";
} else {
echo "Solution 2: result is <= then PHP_INT_MAX\n";
}
And output is wrong:
Solution 1: result is > then PHP_INT_MAX
Solution 2: result is > then PHP_INT_MAX
Does anybody knows what is going on, and how to reliably check the value against PHP_INT_MAX
?
Tested on Linux, 64bit system, PHP 7.3.18.
Thanks!
UPDATE:
- After reading all the comments, answers and after lots of experimentation:
In order to roughly detect when double value will go over PHP_INT_MAX you can use:
!filter_var(number_format($result, 0, '.', ''), FILTER_VALIDATE_INT)
$result >= PHP_INT_MAX
(int) $result < 0
(This one assumes that it is expected that $result will be >=0 to start with).
Checkout this example, where I am testing 20,000 numbers around PHP_INT_MAX
:
<?php
function from_scientific_notation($value)
{
$decimalNotation = rtrim(sprintf('%f', $value), '0');
return rtrim($decimalNotation, '.');
}
for ($i = -10000; $i <= 10000; $i += 1) {
$result = (double) PHP_INT_MAX + (double) $i;
if (!filter_var(number_format($result, 0, '.', ''), FILTER_VALIDATE_INT)) {
echo "S1:";
}
if ($result >= PHP_INT_MAX) {
echo "S2:";
}
if ((int) $result < 0) {
echo "S3:";
}
echo "\nPHP_INT_MAX + $i = " .from_scientific_notation($result) . "\n";
}
Output:
...
PHP_INT_MAX + -515 = 9223372036854774784
PHP_INT_MAX + -514 = 9223372036854774784
PHP_INT_MAX + -513 = 9223372036854774784
S1:S2:S3:
PHP_INT_MAX + -512 = 9223372036854775808
S1:S2:S3:
PHP_INT_MAX + -511 = 9223372036854775808
....
Please note loss of precision, the number PHP_INT_MAX - 512
is detected to be too larger then PHP_INT_MAX
. Depending on the situation this inaccuracy might be or might not be acceptable.
- But really, the only correct way of working with such large numbers would be to use libraries like
bcmath
orgmp
(as mentioned in the answer below). But again - that might require a major refactor which might be out of the question.