The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  ВХОД  слежка  RSS
"Большие числа в PHP"
Вариант для распечатки  
Пред. тема | След. тема 
Форумы WEB технологии (Public)
Изначальное сообщение [Проследить за развитием треда]

"Большие числа в PHP" 
Сообщение от Мика emailИскать по авторуВ закладки(ok) on 05-Сен-05, 19:24  (MSK)
Есть функция преобразования строки IP-адреса в число, и есть функция преобразования обратно.
function ipstr2num($str)
{
    $res = 0;
    $str = explode(".", $str);
    $res = ($str[0] << 24) + ($str[1] << 16) + ($str[2] << 8) + $str[3];
    return $res;
}

function ipnum2str($num)
{
    $res = "";
    $res .= ($num & 0xFF000000) >> 24;
    $res .= ".";
    $res .= ($num & 0x00FF0000) >> 16;
    $res .= ".";
    $res .= ($num & 0x0000FF00) >> 8;
    $res .= ".";
    $res .= ($num & 0x000000FF);
    return $res;
}

После преобразования число получается 10 десятичных разрядов и число превращается в отрицательное. Пишу его в базу с помошью форматирования sprintf("%u",ipstr2num($IP)) и значение сохраняется нормально. А проблема получается в том, что когда пытаюсь преобразовать его обратно первый октет никак не получается больше 127, соответственно остальные тоже неправильно.
Вопрос - какие возможности PHP мне использовать для работы с большими числами ?!

  Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

 Оглавление

Индекс форумов | Темы | Пред. тема | След. тема
Сообщения по теме

1. "Большие числа в PHP" 
Сообщение от mephius emailИскать по авторуВ закладки(ok) on 05-Сен-05, 20:34  (MSK)
>Есть функция преобразования строки IP-адреса в число, и есть функция преобразования обратно.
>
>function ipstr2num($str)
>{
>    $res = 0;
>    $str = explode(".", $str);
>    $res = ($str[0] << 24) + ($str[1] <<
>16) + ($str[2] << 8) + $str[3];
>    return $res;
>}
>
>function ipnum2str($num)
>{
>    $res = "";
>    $res .= ($num & 0xFF000000) >> 24;
>    $res .= ".";
>    $res .= ($num & 0x00FF0000) >> 16;
>    $res .= ".";
>    $res .= ($num & 0x0000FF00) >> 8;
>    $res .= ".";
>    $res .= ($num & 0x000000FF);
>    return $res;
>}
>
>После преобразования число получается 10 десятичных разрядов и число превращается в отрицательное.
>Пишу его в базу с помошью форматирования sprintf("%u",ipstr2num($IP)) и значение сохраняется
>нормально. А проблема получается в том, что когда пытаюсь преобразовать его
>обратно первый октет никак не получается больше 127, соответственно остальные тоже
>неправильно.
>Вопрос - какие возможности PHP мне использовать для работы с большими числами
>?!


это не столько вопрос больших чисел, сколько вопрос битовых операций.
попробуйте провести битовую операцию сдвига влево числа, большего 127 (возьмем 128) вручную (24 раза умножить на два) и с помощью битовой операции php. получите разные числа. Битовая операция php затронет знаковый разряд и получится отрицательное число (в двоичном виде получится 10101000000000000000000000000000 - неверно). умножение же даст 10000000000000000000000000000000 - верно.
см мануал по битовым операциям - Don't left shift in case it results to number longer than 32 bits.
вот тут-то и порылась собака.

решение вытекает из вышеизложенного (сорри, нет времени набросать - убегаю домой).

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

2. "Большие числа в PHP" 
Сообщение от Мика emailИскать по авторуВ закладки(ok) on 06-Сен-05, 07:31  (MSK)
Сделал так
function ipstr2num($str)
{
    $res = 0;
    $str = explode(".", $str);
    $res = ($str[0] * 16777216) + ($str[1] * 65536) + ($str[2] * 256) + $str[3];
    print $res;
    return $res;
}
, но число получается тем же, соответственно результат никакой..
  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

3. "Большие числа в PHP" 
Сообщение от mephius emailИскать по авторуВ закладки(ok) on 06-Сен-05, 09:38  (MSK)
>Сделал так
>function ipstr2num($str)
>{
>    $res = 0;
>    $str = explode(".", $str);
>    $res = ($str[0] * 16777216) + ($str[1] *
>65536) + ($str[2] * 256) + $str[3];
>    print $res;
>    return $res;
>}
>, но число получается тем же, соответственно результат никакой..

вот так будут выглядеть функции для хранения ip в числовом виде, если учитывать единицу в знаковом разряде:

function ipstr2num($str)
{
    $res = 0;
    $str = explode(".", $str);
    $res = ((int)$str[0] << 24) + ((int)$str[1] << 16) + ((int)$str[2] << 8) + (int)$str[3];
    return $res;
}

function ipnum2str($num)
{
    $res = "";
    $res .= (($num & 0xFF000000) >> 24)<0?(256+(($num & 0xFF000000)>>24)):(($num & 0xFF000000) >> 24);
    $res .= ".";
    $res .= ($num & 0x00FF0000) >> 16;
    $res .= ".";
    $res .= ($num & 0x0000FF00) >> 8;
    $res .= ".";
    $res .= ($num & 0x000000FF);
    return $res;
}

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

4. "Большие числа в PHP" 
Сообщение от Мика emailИскать по авторуВ закладки(ok) on 06-Сен-05, 20:22  (MSK)
Спасибо, совет частично помог, а именно число из строки стало выходить точным, но обратно........................
Я тут сижу и понимаю, что проблема в битовой операции "И".
Для примера возьмем подсеть "192.168.0.0". Набираем в виндовском калькуляторе 192, сдвигаем влево на 8, прибавляем 168, и еще сдвигаем на 16. Получается 3232235520 (это же число дает функция преобразования строки в число), в битах 11000000101010000000000000000000. После операции ($num & 0xFF000000) калькулятор показывает 3221225472, в битах 11000000000000000000000000000000, что верно, а у PHP получается 2130706432, в битах 01111111000000000000000000000000, что после сдвига вправо дает 127..
Только не могу понять как решить проблему..

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

5. "Большие числа в PHP" 
Сообщение от mephius emailИскать по авторуВ закладки(ok) on 07-Сен-05, 11:06  (MSK)
>Спасибо, совет частично помог, а именно число из строки стало выходить точным,
>но обратно........................
>Я тут сижу и понимаю, что проблема в битовой операции "И".
>Для примера возьмем подсеть "192.168.0.0". Набираем в виндовском калькуляторе 192, сдвигаем влево
>на 8, прибавляем 168, и еще сдвигаем на 16. Получается 3232235520
>(это же число дает функция преобразования строки в число), в битах
>11000000101010000000000000000000. После операции ($num & 0xFF000000) калькулятор показывает 3221225472, в битах
>11000000000000000000000000000000, что верно, а у PHP получается 2130706432, в битах 01111111000000000000000000000000,
>что после сдвига вправо дает 127..
>Только не могу понять как решить проблему..

Хм, а у меня нормально работает и туда и обратно. при тех функциях, что я дал, действительно получается отрицательные числа при переводе ip в число (используется знаковый разряд), но это учитывается при переводу обратно и все отрабатывает нормально.

вот, можно посмотреть здесь http://demo.xmlsapiens.org/ip.php

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

6. "Большие числа в PHP" 
Сообщение от GD Искать по авторуВ закладки on 07-Сен-05, 13:48  (MSK)
>Есть функция преобразования строки IP-адреса в число, и есть функция преобразования обратно.
>
>function ipstr2num($str)
>{
>    $res = 0;
>    $str = explode(".", $str);
>    $res = ($str[0] << 24) + ($str[1] <<
>16) + ($str[2] << 8) + $str[3];
>    return $res;
>}
>
>function ipnum2str($num)
>{
>    $res = "";
>    $res .= ($num & 0xFF000000) >> 24;
>    $res .= ".";
>    $res .= ($num & 0x00FF0000) >> 16;
>    $res .= ".";
>    $res .= ($num & 0x0000FF00) >> 8;
>    $res .= ".";
>    $res .= ($num & 0x000000FF);
>    return $res;
>}
>
>После преобразования число получается 10 десятичных разрядов и число превращается в отрицательное.
>Пишу его в базу с помошью форматирования sprintf("%u",ipstr2num($IP)) и значение сохраняется
>нормально. А проблема получается в том, что когда пытаюсь преобразовать его
>обратно первый октет никак не получается больше 127, соответственно остальные тоже
>неправильно.
>Вопрос - какие возможности PHP мне использовать для работы с большими числами
>?!


а http://ru2.php.net/ip2long не подойдет?

  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх

7. "Большие числа в PHP" 
Сообщение от Мика emailИскать по авторуВ закладки(ok) on 07-Сен-05, 18:17  (MSK)
Спасибо всем за помощь!!! Я нашел решение!!!
Заглянул в исходники на Перле и понял, что эта проблема не только у РНР!.
Число у меня извлекалось из базы данных и сразу передавалось функции - ipnum2str($res["IP"]). Когда я проверил число в массиве, то обнаружил, что уже в нём обрезан крайний бит. В Перле, при каждом вызове функции, сделано сложение с нулем - ipstr2num($ip)+0.
Теперь я делаю так $res["IP"] += 0 и всё работает!!
Поздравляю всех и себя =)
  Удалить Правка | Высказать мнение | Ответить | Рекомендовать в FAQ | Cообщить модератору | Наверх


Архив | Удалить

Индекс форумов | Темы | Пред. тема | След. тема
Оцените тред (1=ужас, 5=супер)? [ 1 | 2 | 3 | 4 | 5 ]
Пожалуйста, прежде чем написать сообщение, ознакомьтесь с данными рекомендациями.




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру