php - 将 IPv6 地址转换为 64 位双精度
问题描述
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 位 int 可以的所有值,甚至更多。
我确信有一个现成的函数/库/一段代码可以从 IPv6 => double 转换。任何人都可以发布代码来做到这一点,或者链接?
谢谢
最好是 PHP,但你可以发布其他语言的代码,我会翻译成 PHP。
PS 我读过这个相关的问题Can double be used to store and saferetrieve 128 bit IPv6? 但 IMO 的答案是错误的,因为您不需要与 IPv6 地址(128 位)具有相同位的变量。您只需要它能够假设 IPv6 可以具有的所有可能值。正如我上面所说,尽管它只是 64 位,但 double 可以表示 128 位 int 的所有可能值,甚至更多。
这怎么可能?
这就是浮点寄存器的魔力。与整数计算相比,它们在计算时占用更多 CPU,但功能更强大。
编辑:为什么我需要这种转换:我有一个 MySQL 表,其中 IPv6 地址定义为 DECIMAL(39),它是一个 39 位整数。如果是 IPv6,我需要通过访问者的地址查询该表。
解决方案
但是,任何语言的双精度浮点变量都可以高达 ±1.79769313486231570e+308 ,因此它绝对可以假设 128 位 int 可以的所有值,甚至更多。
这个假设是错误的。双精度浮点变量不能假定 128 位 int 可以的所有值。
这是因为计算机科学中的浮点类型精度有限。一旦得到大于 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,adouble
将无法表示它。
所以不,不可能在double
64 位浮点值定义的空间中表示整个 IPv6 地址范围。
请参阅浮点数学是否损坏?有关浮点数学如何在计算机中工作的更详细的细分。
您的部分问题似乎是类型之间的一些混淆。计算机科学中的DECIMAL
类型与double
类型不同。decimal
类型通常是某种 BigNum 实现。他们可能可以存储完整的 IPv6 地址,但它不会仅以 64 位存储。它将使用数据库实现所需的任何位数(可能超过 128 位,因为decimal
通常设计用于处理定点数学)。
如果您需要将 IPv6 地址保存在数据库中,您可能可以使用类型来摆脱它decimal(39)
,但为了安全起见,您应该使用以下其中之一:
- 显式大小的 128 位整数字段
- 一个 16 字节
VARCHAR
(或其他类似字符串的字段),每个字符节省 8 位 - 一个 64 字节的
VARCHAR
字段,将 IP 地址保存在十六进制编码的字符串中(就像它们通常的表示方式一样)。 VARCHAR
将 IP 地址保存在 BASE64 编码字符串中的 22 字节字段
推荐阅读
- node.js - 找不到 newEventHub 函数
- javascript - 反应路由器 v4 导航/重新加载相同的路由
- batch-file - 将一个文件中的行中的所有字符精确打印到批处理文件中的一个文件
- mysql - MySQL:从另一个数据库添加数据,从特定行开始,user_id 是主要的,需要插入从 20 开始的递增数字
- functional-programming - 为什么这个函数应该返回 false 时返回 true?
- java - Android - 无法使用 Retrofit2 获取 JSON
- java - 使用 CardLayout 时如何将 addWindowListener 添加到所有面板?
- jquery - 用 textarea 聚焦但光标不可见
- python - How to make subplots to show a list of legends
- android - 安卓工作室 3.1.3;没有错误;Logcat 扭曲的内容表示