将 IPv6 地址转换为 64 位双精度
Converting IPv6 addresses to 64-bit double
IPv6 地址实际上是 128 位无符号整数,因此它们的范围
值为 [0, 3.40 × 10^38]
A 128-bit register can store 2^128 (over 3.40 × 10^38) different values. The range of integer values that can be stored in 128 bits depends on the integer representation used. With the two most common representations, the range is 0 through 340,282,366,920,938,463,463,374,607,431,768,211,455 (2^128 − 1) for representation as an (unsigned) binary number,
https://en.wikipedia.org/wiki/128-bit
但是,无论使用何种语言,双精度浮点变量都可以高达 ±1.79769313486231570e+308 ,因此它绝对可以采用 128 位 int 可以采用的所有值,甚至更多。
我确定有现成的 function/library/piece 代码可以从 IPv6 转换 => double。
任何人 post 代码都可以做到这一点,或者 link?
谢谢
最好是 PHP,但您可以 post 使用其他语言编写代码,我会翻译成 PHP。
P.S。
我读过这个相关问题 但 IMO 的答案是错误的,因为你 不需要 一个与 IPv6 地址(128 位)具有相同位的变量.
您只需要它能够假定 IPv6 可以具有的所有可能值。
正如我上面所说的,double 可以表示 128 位 int 甚至更多的所有可能值,尽管它只是 64 位。
这怎么可能?
这就是浮点寄存器的神奇之处。
与整数相比,它们更 CPU 更密集地进行计算,但更强大。
编辑:为什么我需要这种转换:
我有一个 MySQL table,IPv6 地址定义为 DECIMAL(39),这是一个 39 位整数。如果是 IPv6,我需要通过访问者的地址查询 table。
A double-precision float variable in whatever language, though, can be as high as ±1.79769313486231570e+308 , so it definitely can assume all the values a 128-bit int can, and even more.
这个假设是错误的。双精度浮点变量可以不假定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
将无法表示它。
所以不,不可能在由 double
定义的 space 中表示整个 IPv6 地址范围,64 位浮点值。
有关浮点数学在计算机中的工作原理的更详细分类,请参阅 Is Floating Point Math Broken?。
您的部分问题似乎是类型之间存在一些混淆。计算机科学中的 DECIMAL
类型与 double
类型不同。 decimal
类型通常是某种 BigNum 实现。他们可能 可以 存储整个 IPv6 地址,但它不会只用 64 位来存储。它将使用数据库实现所需的任何位数(可能超过 128 位,因为 decimal
通常设计用于处理定点数学)。
如果您需要在数据库中保存 IPv6 地址,您可能可以使用 decimal(39)
类型,但为了安全起见,您应该改用其中之一:
- 明确大小的 128 位整数字段
- 每个字符节省 8 位的 16 字节
VARCHAR
(或其他类似字符串的字段)
- 一个 64 字节的
VARCHAR
字段,以十六进制编码的字符串形式保存 IP 地址(就像它们通常的表示方式一样)。
- 一个 22 字节的
VARCHAR
字段,以 BASE64 编码的字符串形式保存 IP 地址
IPv6 地址实际上是 128 位无符号整数,因此它们的范围 值为 [0, 3.40 × 10^38]
A 128-bit register can store 2^128 (over 3.40 × 10^38) different values. The range of integer values that can be stored in 128 bits depends on the integer representation used. With the two most common representations, the range is 0 through 340,282,366,920,938,463,463,374,607,431,768,211,455 (2^128 − 1) for representation as an (unsigned) binary number, https://en.wikipedia.org/wiki/128-bit
但是,无论使用何种语言,双精度浮点变量都可以高达 ±1.79769313486231570e+308 ,因此它绝对可以采用 128 位 int 可以采用的所有值,甚至更多。
我确定有现成的 function/library/piece 代码可以从 IPv6 转换 => double。 任何人 post 代码都可以做到这一点,或者 link?
谢谢
最好是 PHP,但您可以 post 使用其他语言编写代码,我会翻译成 PHP。
P.S。
我读过这个相关问题
这怎么可能?
这就是浮点寄存器的神奇之处。 与整数相比,它们更 CPU 更密集地进行计算,但更强大。
编辑:为什么我需要这种转换: 我有一个 MySQL table,IPv6 地址定义为 DECIMAL(39),这是一个 39 位整数。如果是 IPv6,我需要通过访问者的地址查询 table。
A double-precision float variable in whatever language, though, can be as high as ±1.79769313486231570e+308 , so it definitely can assume all the values a 128-bit int can, and even more.
这个假设是错误的。双精度浮点变量可以不假定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
将无法表示它。
所以不,不可能在由 double
定义的 space 中表示整个 IPv6 地址范围,64 位浮点值。
有关浮点数学在计算机中的工作原理的更详细分类,请参阅 Is Floating Point Math Broken?。
您的部分问题似乎是类型之间存在一些混淆。计算机科学中的 DECIMAL
类型与 double
类型不同。 decimal
类型通常是某种 BigNum 实现。他们可能 可以 存储整个 IPv6 地址,但它不会只用 64 位来存储。它将使用数据库实现所需的任何位数(可能超过 128 位,因为 decimal
通常设计用于处理定点数学)。
如果您需要在数据库中保存 IPv6 地址,您可能可以使用 decimal(39)
类型,但为了安全起见,您应该改用其中之一:
- 明确大小的 128 位整数字段
- 每个字符节省 8 位的 16 字节
VARCHAR
(或其他类似字符串的字段) - 一个 64 字节的
VARCHAR
字段,以十六进制编码的字符串形式保存 IP 地址(就像它们通常的表示方式一样)。 - 一个 22 字节的
VARCHAR
字段,以 BASE64 编码的字符串形式保存 IP 地址