Преобразование адресов IPv6 в 64-битный двойной - PullRequest
0 голосов
/ 12 марта 2019

IPv6-адреса являются скрытыми 128-битными целыми числами без знака, поэтому их диапазон значений равен [0, 3.40 × 10 ^ 38]

128-битный регистр может хранить 2 ^ 128 (свыше 3,40 × 10 ^ 38) разные значения.Диапазон целочисленных значений, которые могут быть сохранены в 128 битах, зависит от используемого целочисленного представления.С двумя наиболее распространенными представлениями диапазон составляет от 0 до 340 282 366 920 938 463 463 374 607 431 768 211 455 (2 ^ 128 - 1) для представления в виде двоичного числа (без знака), https://en.wikipedia.org/wiki/128-bit

Переменная с плавающей запятой двойной точности в любом случаеязык, однако, может достигать ± 1.79769313486231570e + 308, поэтому он определенно может принимать все значения, которые может использовать 128-битное целое число, и даже больше.

Я уверен, что есть готовый к-используйте функцию / библиотеку / фрагмент кода для преобразования из IPv6 => double.Может кто-нибудь опубликовать код для этого или ссылку?

Спасибо

Желательно PHP, но вы можете разместить код на других языках, и я переведу на PHP.

PS Я прочитал этот связанный вопрос Может удвоитьсяиспользоваться для хранения и безопасного извлечения 128-битного IPv6? , но IMO ответы были неправильными, потому что вам не нужна переменная с теми же битами, что и адрес IPv6 (128-битный).Вам просто нужно, чтобы он мог принять все возможные значения, которые может иметь IPv6.Как я уже говорил выше, double может представлять все возможные значения 128-битного int и даже больше, несмотря на то, что он всего лишь 64-битный.

Как это возможно?

Это магия регистров с плавающей запятой.Они более ресурсоемки для выполнения вычислений по сравнению с целочисленными, но более мощны.

РЕДАКТИРОВАТЬ: Зачем мне нужно это преобразование: у меня есть таблица MySQL с адресами IPv6, определенными как DECIMAL (39),который является 39-значный Int.Мне нужно запросить эту таблицу по адресу посетителя, если это IPv6.

1 Ответ

11 голосов
/ 12 марта 2019

Плавающая переменная двойной точности на любом языке, тем не менее, может достигать ± 1.79769313486231570e + 308, поэтому она определенно может принимать все значения, которые может использовать 128-битное целое число, и даже больше.

Это предположение неверно. Переменная с плавающей запятой двойной точности может не принимать все значения, которые может использовать 128-битное целое число.

Это потому, что тип с плавающей запятой в информатике имеет ограниченную точность. Как только вы доберетесь до чисел больше 2 ^ 52, вы больше не сможете представлять отдельные целые числа в этом диапазоне. Вы ограничены 2 ^ 52, 2 ^ 52 + 2, 2 ^ 52 + 4, 2 ^ 52 + 6, ... пока не достигнете 2 ^ 53, и в этот момент вы потеряете большую точность, представляя только значения 2 ^ 53, 2 ^ 53 + 4, 2 ^ 53 + 8, 2 ^ 53 + 12, ...

Так что, если, скажем, ваш IPv6-адрес равен 2 ^ 52 + 1, double не сможет его представить.

Так что нет, невозможно представить весь диапазон адресов IPv6 в пространстве, определенном 64-битным значением с плавающей запятой double.

См. Математика с плавающей точкой сломана? для более подробного описания того, как математика с плавающей точкой работает в компьютерах.


Частью вашей проблемы является некоторая путаница между типами. Тип DECIMAL в информатике - это не тот же тип, что и тип double. decimal типы - это, как правило, реализация BigNum. Они, вероятно, могут хранить весь адрес IPv6, но он не собирается делать это только в 64-битной версии. Он будет использовать любое количество бит, необходимое для реализации базы данных (вероятно, более 128 бит, поскольку decimal обычно предназначен для обработки математики с фиксированной запятой).

Если вам нужно сохранить IPv6-адрес в базе данных, вы могли бы быть в состоянии обойтись без него с типом decimal(39), но для безопасности вам следует использовать один из них вместо :

  • 128-битное целочисленное поле явного размера
  • 16-байтовое VARCHAR (или другое строковое поле), которое сохраняет 8 битов на символ
  • 64-байтовое поле VARCHAR, которое сохраняет IP-адрес в шестнадцатеричной строке (например, как они обычно представлены).
  • 22-байтовое VARCHAR поле, которое сохраняет IP-адрес в BASE64-кодированной строке
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...