Intereting Posts
добавление счетчика на страницу php для подсчета уникальных посетителей WooCommerce – Пользовательское уведомление на страницах заказа «Спасибо» и «Моя учетная запись» Список категорий по автору ~ С COUNTER ~ (WordPress) window.history.pushState обновление браузера PHP-сервер на локальной машине? Yii2: Как показать проверенные значения в CheckboxList Ошибки анализа не отображаются Выполнять роль сервера Javascript используйте exec (); в php-скрипте для отправки электронной почты из оболочки Запрос jquery $ .ajax остается в ожидании Групповые многомерные массивы на основе двух значений в PHP Symfony2, Как передать параметры сортировки и направления с помощью KnpPaginatorBundle и QueryBuilder Плюсы / минусы использования index.php? Q = путь / вместо index.php / path / при маршрутизации URL-адресов? диапазон чисел с плавающей точкой в ​​php. -0 плавает? Переходы строк заголовка PHP и HTTP: какой символ используется для представления?

php: ip2long возвращает отрицательный val

function ip_address_to_number($IPaddress) { if(!$IPaddress) { return false; } else { $ips = split('\.',$IPaddress); return($ips[3] + $ips[2]*256 + $ips[1]*65536 + $ips[0]*16777216); } } 

эта функция выполняет тот же код, что и связанная с php функция ip2long. однако, когда я печатаю эти 2 значения, я получаю 2 разных результата. Зачем? (im, используя php 5.2.10 в рабочей среде).

 ip2long('200.117.248.17'); //returns **-931792879** ip_address_to_number('200.117.248.17'); // returns **3363174417** 

Применяется и продолжается здесь: Показывая мою страну на основе моего IP, оптимизирован mysql

 glopes @ nebm: ~ $ php -r "printf ('% u', -931792879);
 3363174417

Вот так. Я предполагаю, что вы находитесь в системе с 32-битными ints, и ваш ip_address_to_number фактически возвращает float.

Вы видите, что с 32-битным ints ваше максимальное положительное целое число (2^31) - 1 = 2 147 483 647 , поэтому целое число обтекает.

Если вы хотите имитировать поведение функции PHP, выполните следующие действия:

 function ip_address_to_number($IPaddress) { if(!$IPaddress) { return false; } else { $ips = split('\.',$IPaddress); return($ips[3] | $ips[2] << 8 | $ips[1] << 16 | $ips[0] << 24); } } 

(кстати, split устарел)

Попробуйте это вместо этого:

 $ip = sprintf('%u', ip2long($_SERVER['REMOTE_ADDR'])); 

Затем sprintf записывает его как целое число без знака.

  $ips[3] = 17 + $ips[2] * 256 = 248 * 256 = 63488 + $ips[1] * 65536 = 117 * 65536 = 7667712 + $ips[0] * 16777216 = 200 * 16777216 = 3355443200 = 3363174417 

Максимальное целочисленное значение PHP max (32-разрядное) – 2147483647, что составляет <3363174417

Цитирование с страницы руководства ip2long () PHP

Примечание. Поскольку целочисленный тип PHP подписан, а многие IP-адреса приводят к отрицательным целым числам, вам нужно использовать форматирование «% u» sprintf () или printf (), чтобы получить строковое представление неподписанного IP-адреса.

Вы можете использовать –

 // IP Address to Number function inet_aton($ip) { $ip = trim($ip); if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) return 0; return sprintf("%u", ip2long($ip)); } // Number to IP Address function inet_ntoa($num) { $num = trim($num); if ($num == "0") return "0.0.0.0"; return long2ip(-(4294967295 - ($num - 1))); } 
 <?php function _ip2long($input) { $r = null; if (is_string($input)) { $_input = trim($input); if (filter_var($_input, FILTER_VALIDATE_IP)) { $PRE_r = explode('.', $_input); $r = ($PRE_r[0] * pow(256, 3)) + ($PRE_r[1] * pow(256, 2)) + ($PRE_r[2] * 256) + ($PRE_r[0]); } else { $r = false; } } else { $r = false; } return ($r); } $out = _ip2long('127.0.0.1'); if (false === $out) { print('Invalid IP'); } else { print($out); } ?> 

ip2long ли некоторые тесты производительности, чтобы сравнить запуск ip2long через sprintf vs array ip2long а затем раз или побитовое смещение:

 <?php header ('Content-Type: text/plain'); function ip_range($start, $count) { $start = ip2long($start); return array_map('long2ip', range($start, $start + $count) ); } $iterations = 500000; $results = array(); $ips = ip_range('192.168.1.1', $iterations); $time = microtime(true); foreach ($ips as $ip) { $result = sprintf('%u', ip2long($ip)); } $time = microtime(true) - $time; $results['ip2long'] = array ('total' => $time, 'cycles' => $iterations, 'average' => ($time / $iterations) . 's', 'speed' => ($iterations/$time) . ' hashes per second.' ); $time = microtime(true); foreach ($ips as $ip) { $aIp = explode('.', $ip); if (count($aIp) == 4) { $result = /*sprintf('%u',*/ $aIp[0]*16777216 + $aIp[1]*65536 + $aIp[2]*256 + $aIp[3] /*)*/; } else { $result = false; } } $time = microtime(true) - $time; $results['explode multiple'] = array ('total' => $time, 'cycles' => $iterations, 'average' => ($time / $iterations) . 's', 'speed' => ($iterations/$time) . ' hashes per second.' ); $time = microtime(true); foreach ($ips as $ip) { $aIp = explode('.', $ip); if (count($aIp) == 4) { $result = /*sprintf('%u',*/ $aIp[3] | $aIp[2] << 8 | $aIp[1] << 16 | $aIp[0] << 24 /*)*/; } else { $result = false; } } $time = microtime(true) - $time; $results['explode bitwise'] = array ('total' => $time, 'cycles' => $iterations, 'average' => ($time / $iterations) . 's', 'speed' => ($iterations/$time) . ' hashes per second.' ); die(var_dump($results)); 

Вот результаты:

 array(3) { ["ip2long"]=> array(4) { ["total"]=> float(0.92530012130737) ["cycles"]=> int(500000) ["average"]=> string(19) "1.8506002426147E-6s" ["speed"]=> string(34) "540365.21609177 hashes per second." } ["explode multiple"]=> array(4) { ["total"]=> float(0.91870212554932) ["cycles"]=> int(500000) ["average"]=> string(19) "1.8374042510986E-6s" ["speed"]=> string(34) "544246.04678153 hashes per second." } ["explode bitwise"]=> array(4) { ["total"]=> float(0.9184091091156) ["cycles"]=> int(500000) ["average"]=> string(19) "1.8368182182312E-6s" ["speed"]=> string(34) "544419.68730197 hashes per second." } } 

При обертывании побитового и умножаемого в sprintf они медленнее ip2long но поскольку они не нужны, они быстрее.