十进制 IP 地址

“十进制网址”这个词汇, 从诞生之日起就一直摆脱不掉一双引号, 关于这项牛X技术的文章请自行搜索.

具体的实现过程是这样的:

今有IP一枚: 10.1.2.3

则”十进制”格式的计算方法是:

1
2
3
10*256^3 + 1*256^2 + 2*256^1 + 3*256^0
167772160 + 65535 + 512 + 3
167838211

逆向运算就是求商取余的过程.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def decimal_ip_transform(ip)
powers_256 = (0..3).map { |p|
256**p
}.reverse.freeze

case ip
when Integer
powers_256.map { |p|
[ip/p, ip %= p].first.to_s
}.join(".")
when String
ip.scan(/\d{1,3}/).zip(powers_256).inject(0) { |acc,a|
acc + a.first.to_i*a.last
}
end
end

可是这有什么用呢? 申请科研经费?

Stop! 如果你这样想, 请你离开, 谢谢配合!

====================虚荣与务实的分隔线====================

务实派请往下看:

最近有个需求是用IP地址来区分一种终端设备的地理位置, 需要在数据库里记录IP地址对应的设备信息.

直接将”192.168.0.3”这样的字符串保存起来, 读取时不太容易匹配, 如果加长到”192.168.000.003”的话就能支持排序的过滤等操作, 可是体积也变大了了.

如何缩小这一列的宽度的同时实现需求呢? 上文提到的方法值得一试, 把字符串转化成整数保存, 范围在 0 到 4294967295 之间, 而且是线性增长的, 相邻的IP字符串转化的数字也是相邻的, 查找 BETWEEN 167772160 AND 167772160+255 肯定要比查找 LIKE “10.0.0.%” 快的多吧!

PS: 文中除了代码是真的, 其它全是假的, 例子也是假的, 只是为了记录突然冒出来的怪异想法, 关于文章题目请勿深究.