Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why php thinks large ints are floats (but only sometimes)?

Tags:

php

Sorry for the bad title, but I dunno how to call this.

echo rand(0,10e20) . "\n"; // bad
echo rand(0,10e19) . "\n"; // bad
echo rand(0,10e18) . "\n"; // bad
echo rand(0,10e17) . "\n"; // OK
echo rand(0,10e16) . "\n";
echo rand(0,10e15) . "\n\n";

var_dump(10e20); // float
var_dump(10e15); // float

Output:

Warning: rand() expects parameter 2 to be integer, float given in /srv/webroot-sandbox/index.php(73) : eval()'d code on line 1

Warning: rand() expects parameter 2 to be integer, float given in /srv/webroot-sandbox/index.php(73) : eval()'d code on line 2

Warning: rand() expects parameter 2 to be integer, float given in /srv/webroot-sandbox/index.php(73) : eval()'d code on line 3

578009006101638016
69608699344098568
7596902768127620

float(1.0E+21)
float(1.0E+16)

Can someone explain what's going on? This is PHP 7, it worked fine in PHP 5 (well, at least I didn't get any warnings).

like image 603
MightyPork Avatar asked Mar 02 '16 19:03

MightyPork


People also ask

Is int bigger than float?

The precision of the float for large numbers is much lower than an int.

Are floats and ints the same size?

6 Answers. Show activity on this post. They are totally different - typically int is just a straightforward 2's complement signed integer, while float is a single precision floating point representation with 23 bits of mantissa, 8 bits exponent and 1 bit sign (see http://en.wikipedia.org/wiki/IEEE_754-2008).


2 Answers

PHP ints are signed 64bit values (unless you're on a 32bit install), so they go (roughly)

-9,223,372,036,854,775,808 -> +9,223,372,036,854,775,808

In scientific notation, -9.2e18 -> +9.2e18

So your "bad" values are simply integers that are too large to store as integers, and PHP is converting to float to try and preserve as much of the value as is possible.

And since you have 10e18, that's actually 1e19, and outside the max_int range.

like image 147
Marc B Avatar answered Nov 09 '22 02:11

Marc B


Your question can be platform dependent as the integer range of a:

  • 32 bit platform is -2,147,483,648 to 2,147,483,647
  • 64 bit platform is -9,223,372,036,854,775,808 to 9,223,372,036,854,775,808

For me, running a 64 bit system it gives the following result.

var_dump(10e20 > PHP_INT_MAX); // true
var_dump(10e19 > PHP_INT_MAX); // true
var_dump(10e18 > PHP_INT_MAX); // true
var_dump(10e17 > PHP_INT_MAX); // false
var_dump(10e16 > PHP_INT_MAX); // false
var_dump(10e15 > PHP_INT_MAX); // false

This output directly correlates with your results and might explain a fiddle or your webhost to show different results.

The reason it behave differently on PHP 7 is explained here:

Previously, internal functions would silently truncate numbers produced from float-to-integer coercions when the float was too large to represent as an integer. Now, an E_WARNING will be emitted and NULL will be returned.

like image 26
Xorifelse Avatar answered Nov 09 '22 03:11

Xorifelse