On Wed, Jun 23, 2010 at 11:09 AM, Ashley Sheridan <ash@xxxxxxxxxxxxxxxxxxxx> wrote: > Out of interest, how does PHP calculate the IP number, as it was my understanding of IP numbers that they can't be negative. > > For example, my IP address is 89.243.156.135 > The four parts as binary: > 01011001 > 11110011 > 10011100 > 10000111 > > From there, I thought that the binary values were concatenated as if they were a string, and then the decimal value worked out from that, giving, in my case, a value of 1509137543. > > How is it possible that PHP can produce negative values from this method? Does it do something else entirely, or is this a case of the integer value overflowing into negative values? (which might explain why the value correctly converts back) > > If so, what would be the best method to get the correct value, as abs() obviously isn't it! > > Thanks, > Ash > http://www.ashleysheridan.co.uk > > It has to do with the storage of the value as a 4-byte integer, as Bob mentioned. The best way I know of in PHP involves either sprintf dechex, or pack/unpack. If you use pack/unpack, just be careful with the endian-ness of the format you choose: <?php $x = ip2long('192.168.0.1'); var_dump($x); // int(-1062731775) var_dump(long2ip($x)); // string(11) "192.168.0.1" var_dump(long2ip(abs($x))); //string(13) "63.87.255.255" var_dump(sprintf('%u', $x)); // string(10) "3232235521" var_dump((float) sprintf('%u', $x)); // float(3232235521) var_dump(pack('L', $x)); // binary value, machine-dependent byte order var_dump(pack('N', $x)); // binary value, big-endian var_dump(pack('V', $x)); // binary value, little-endian var_dump(dechex($x)); // string(8) "c0a80001" ?> I'm not sure how any of these are best passed along to various databases, though. I believe something like this should work, as long as the column defined with a type that will hold the positive value, such as BIGINT (or, perhaps INT(10) UNSIGNED in MySQL, though I think I remember having issues with that type). $sql = sprintf('INSERT INTO `mytable` (`ip_address`) VALUES (%u)', ip2long($ip)); I do most of my development with SQL Server, so I often just pass the value as a 4-byte integer (or sometimes even in dotted notation) to a stored procedure and then let T-SQL do the work. Andrew -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php