php sprintf bigint,关于ip地址存储类型的探讨

关于ip地址存储的方法, ip地址很多人都用char方式存储, 但我建议还是觉得用整数来存储读取更快.

ip地址转整数的方式比较多, 我逐一说明一下, 部分代码参考网友:Tsung的文章.

1. 用ip2long ip地址转整数

ip2long() 转出来的数值在32位机器转出负数, 系统版本 32bits 和 64bits 转换的结果不一样.

32 bits ip2long(): -2147483648 ~ 214748364764

64 bits ip2long(): 0 ~ 4294967295

32bits 系统测试ip2long()

ip2long('127.255.255.255'); // 2147483647 = 十进位的最大值

ip2long('255.255.255.255'); // -1

ip2long('255.255.255.254'); // -2

ip2long('192.168.1.2'); // -1062731518

64bits 系统测试ip2long()

ip2long('127.255.255.255'); // 2147483647 = 十进位的最大值

ip2long('255.255.255.255'); // 4294967295

ip2long('255.255.255.254'); // 4294967294

ip2long('192.168.1.2'); // 3232235778

知道问题是 32bits 系统造成的, 就很好解决萝~

方法1. ip2long 转成二进位, 再转回十进位避免负值

echo bindec(decbin(ip2long('192.168.1.2'))); // 3232235778

?>

老修备注一下, 这个方法ipv4和ipv6通吃, 数据存储格式要用Unsigned 无标签int类型.

方法2. 可避免ipv4转换后产生负数的另一种算法:

// 自己做转换, 这方法计算出来的数值是正确的.(32bits / 64bits 皆正确)

function iptolong($ip)

{

list($a, $b, $c, $d) = split('.', $ip);

$ip_long = (($a * 256 + $b) * 256 + $c) * 256 + $d;

return $ip_long;//如果加上intval($ip_long);会产生负数

}

?>

此方法同样有的ip地址会产生bigint值.

注: intval 在 32 bits / 64 bits 最大值是不同的:

The maximum value depends on the system.

32 bit systems have a maximum signed integer range of -2147483648 to 2147483647.

So for example on such a system, intval('1000000000000') will return 2147483647.

The maximum signed integer value for 64 bit systems is 9223372036854775807.

方法3. 使用 printf("%u")

$ipbigint = sprintf("%u", ip2long('192.168.1.2'));

?>

这里要注意的是printf 和sprintf的区别, printf是直接输出给浏览器了, 相当于echo (sprintf());

方法4. 使用mysql的 inet_aton 转换函数.

我不建议在mysql 的查询中做数据运算, 这会给脆弱的数据库造成额外的压力, 能php解决的尽量不要放到数据库里操作.

不过方法还是分享一下:

select * from iplist where inet_aton(ip)=inet_aton('{$ip}')

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值