I am dealing with data that involves very large primary keys (12 digits). When I try to put the data in an array in the form id => value, the index is not assigned properly.
$test = array(190337172011 => 'Apple');
print_r($test);
Result:
Array ( [1358610987] => Apple )
Sometimes it even results in a negative number. Why does this happen? Is it a bug?
I am running PHP 5.3.10 on IIS.
The size of an integer is platform-dependent, although a maximum value of about two billion is the usual value (that's 32 bits signed). 64-bit platforms usually have a maximum value of about 9E18. PHP does not support unsigned integers. Integer size can be determined using the constant PHP_INT_SIZE, and maximum value using the constant PHP_INT_MAX since PHP 4.4.0 and PHP 5.0.5.
source: http://php.net/manual/en/language.types.integer.php
You are using a 32 bit PHP version on probably a 32 bit windows operating system, for example Windows XP.
For numerical array indexes PHP uses the integer variable type to store the keys. Those are limited. This limitation becomes visible if you choose a value greater than the limit which will either trigger a max or a turn-around depending on the PHP version and the operating system.
The value 190337172011 is too large of the integer type on your system, that's why you get a cap through roundtrip with a result of 1358610987. Roundtrip means, that after the possible maximum positive number, the next number is the lowest possible number, which is the "largest" negative number that can be expressed. That's why you get negative numbers as well.
You can work around that by storing the values as string keys which needs some pre-fixing:
$test = array('ID' . 190337172011 => 'Apple');
print_r($test);
This is normally enough to make your code more portable. You can choose any string prefix as you like, ID is just exemplary, but you need at least one non-numeric character.
Related
Is there a way to check greater values then "2147483648"?
I have to work with numbers up to "6.73297395398192e212" (2^707).
The data is stored in a mysql-database as float.
Maybe I'm just using the wrong search terms or there is not a good way.
A double precision value uses 8 bytes, and you obviously cannot store 707 bits in those (which I assume you are trying to do). It can store a value of 1e308 by an approximation that costs precision in the lower digits, which makes it a bad choice for storing data that you want to do bitwise operations on. For bitwise operation on 8 bytes, you can use bigint.
Since MySQL 8, MySQL supports bitwise operations on binary string of arbitrary length, so you should store your value that way - a bit array is basically a binary string anyway. You cannot treat them as numbers though (e.g. add or multiply them like integers).
For earlier MySQL versions, bit operations on binary strings were limited to 8 bytes. You should still store your bits as a binary string (which allows for an easy upgrade), and write a small function that does the operation e.g. bytewise.
The operation 1539 | 0xfffff800 returns -509 in JavaScript and Python 2.7.
In PHP I get 4294966787.
Does anybody know why and could explain that to me. I would love to know how I get the expected result in PHP as well.
1539 | 0xfffff800 = 4294966787 (= 0xFFFFFE03)
This is perfectly right. So, PHP is right.
If you would like to have both positive and negative integers, you need some mechanism to determine whether the number is negative. This is usually done using the 2-complement of the number. You can negate a number by just inverting all the bits of the number and then add 1 to it. In order to avoid ambiguities, you cannot use all the bits of your integer variable. You cannot use the highest bit in this case. The highest bit is reserved as a sign bit. (If you would not do so, you never know if your number is a big positive number or a negative number.)
For exammple with an 8 bit integer variable, you would be able to represent numbers from 0 to 255. If you need signed values, you can represent number from -128 (1000 000 binary) to +127 (0111 1111).
In your example, you have a 32 bit number which has its highest bit set. In Python and JavaScript, it's interpreted as negative number, as they apparently have 32 bit variables, and there, the highest bit is set. They interpret that as negative number. So, the result of your calculation is also negative.
In the PHP version you are using, the integer variable seems to be 64 bit long and only the lower 32 bits are used. The highest bit (bit 63) is not set, so PHP interprets this number as positive. Depending on what you want to achive, you may want to fill up all bits from bit 32 to bit 63 with 1s which will create a negative number...
What is the maximum input value for a seed in PHP? Is it 2^32? 2^64? No limit?
I cannot seem to find an answer in PHP documentation.
php_srand takes a long, and it calls one of srandom, srand48, or srand (depending upon compilation defines).
It casts the seed value to an int in the case of srandom/srand, but passes the full long-typed value through to srand48 - so then it comes down to implementation of the system/stdlib random functions (and actual size of int).
Also, considering that mt_srand takes a uint32, I'd say it's reliable to expect 32-bit seeds to be considered distinct (even if they start the same sequence). A 64-bit seed is the upper value limit (even if the entire seed is not used), but is only realizable in a 64-bit version of PHP.
Any non-integer value (i.e. float) supplied as a seed will be coerced to an integer. The actual php_srand C function is only called after coercing the supplied PHP value to a long in the wrapper.
You can use getrandmax() to determine the maximum value. ref: http://www.php.net/manual/en/function.getrandmax.php
srand takes an int which I assume is a 32-bit number on 32-bit machines according to the docs. and 64 on 64-bit machines.
I am trying this out, but am unable to store large value
$var = rand(100000000000000,999999999999999);
echo $var; // prints a 9 digit value(largest possible)
How to get a desired value ?
From the manual:
The size of an integer is platform-dependent, although a maximum value of about two billion is the usual value (that's 32 bits signed). 64-bit platforms usually have a maximum value of about 9E18. PHP does not support unsigned integers. Integer size can be determined using the constant PHP_INT_SIZE, and maximum value using the constant PHP_INT_MAX since PHP 4.4.0 and PHP 5.0.5.
...
If PHP encounters a number beyond the bounds of the integer type, it will be interpreted as a float instead. Also, an operation which results in a number beyond the bounds of the integer type will return a float instead.
BC Math and GMP are the (only?) way to manipulate this limitation.
PHP ints are typically 32 bits. Other packages provide higher-precision ints: http://php.net/manual/en/language.types.integer.php
If you need to work with very large numbers I have found success with BC Math. Here is a link to everything you need to know:
http://php.net/manual/en/book.bc.php
If you want to generate the number and manipulate as a native type, you can't with most PHP installations (either you have 32 or 64 bit ints and nothing else), as the other answers have already stated. However, if you are just generating a number and want to pass it around a possible trick is to just concatenate strings:
$var = rand(0,PHP_INT_MAX).str_pad(rand(0, 999999999), 9, 0, STR_PAD_LEFT);
echo $var;
On a platform in which PHP uses a 32 bit integer, this allows you to get a near random integer (as a string) that is bigger than 32 bits ( > 10 decimal places). Of course, there is a bias in this construction which means you won't cover all the numbers with the same probability. The limits of the rand() calls obey normal decimal rules so its simple to adjust the upper bound of the number you want.
If all you're doing is storing/transmitting/showing this value, the string will be just fine. Equality and greater/less than tests will also work. Just don't do any math with it.
Lets assume we are talking about 32bit system.
PHP doesn't support unsigned INT. It means that INT value should be between -2,147,483,648 and 2,147,483,647 values. And INT takes 4 bytes to store a value which are 32 bits length.
So does it mean that I have only 31 bits for value and 1 bit for sign? Or I can use whole 32 bits to store a value?
You are using the whole 32 bits. It's just that the default output functions interpret it as signed integer. If you want to display the value "raw" use:
printf("%u", -1); // %u for unsigned
Since PHP handles the integers signed internally however, you can only use bit arithmetics, but not addition/multiplication etc. with them - if you expect them to behave like unsigned ints.
2147483647 is the usual value 2^31-1. 1 bit for sign and -1 because we also represent 0.
from the manual:
"The size of an integer is platform-dependent, although a maximum value of about two billion is the usual value (that's 32 bits signed). 64-bit platforms usually have a maximum value of about 9E18. PHP does not support unsigned integers. Integer size can be determined using the constant PHP_INT_SIZE, and maximum value using the constant PHP_INT_MAX since PHP 4.4.0 and PHP 5.0.5."
As far as i know on a 32-bit system the largest positive integer possible is 2147483647 values above will be float values, since a float value in php can take values up to 10000000000000.
First of all, if you want to do calculations with huge numbers (say, regulary greater than 10k), you should use the bcmath arbitrary precision module.
Secondly, the official php implementation uses the Two's complement internally to represent numbers, like virtually all other compilers and interpreters. Since the entropy of the signed bit (if you count 0 as positive[1]) is 1, and the entropy of 31 bits is, well, 31, you can store 232 = 4 294 967 296 distinct values. How you interpret them is up to your application.
[1] - 0 is neither positive nor negative.
Normally with 32 bit integers the difference between signed and unsigned is just how you interpret the value. For example, (-1)+1 would be 1 for both signed and unsigned, for signed it's obvious and for unsigned it's of course only true if you just chop the overflow off. So you do have 32 bits to store values, it just happens to be so that there's 1 bit that is interpreted differently from the rest.
Two's complement is most frequently used to store numbers, which means that 1 bit is not wasted just for the sign.
http://en.wikipedia.org/wiki/Two's_complement
In PHP if a number overflows the INT_MAX for a platform, it converts it to a floating point value.
Yes if it would have used unsigned integer it will use 32 bit to store it as you don't need sign in that case but as it supports only signed integers a 32 bit systems will have 31 bit for value and 1 bit for sign s0 maximum signed integer range is -2147483648 to 2147483647.