由專案中一個hash2int函數引發的思考

hash2int

/**
 * 计算一个字符串的md5折算成int返回
 * @param type $str
 * @return type
 */
function hash2int($str) {
    $md5str = md5($str, true);
    $one = unpack('l', substr($md5str, 0, 4));
    $two = unpack('l', substr($md5str, 4, 4));
    $three = unpack('l', substr($md5str, 8, 4));
    $four = unpack('l', substr($md5str, 12, 4));
    return current($one) + current($two) + current($three) + current($four);
}

思考一:这个函数有没有优化的空间,直接上代码

function hash2int2($str) {
    $md5str = md5($str, true);
    $arr = unpack('la/lb/lc/ld', $md5str);
    return array_sum($arr);
}

效率大约是上一个函数的4倍(当然这种程度的优化对于一个设计到db等的大项目的效率影响很小)

思考二:pack/unpack在php中的使用

首先熟悉几个概念

  计算机当中通常采用的自己存储方式(字节序)有:大端和小端
  大端序(网络字节序):①多字节传输时,先传高字节;②存储时高位字节在低地址
  小端序:①多直接传输时,先传低位字节;②存储时低位字节放在低地址
  栗子:0x12345678
  大端序:0x12 0x34 0x56 0x78
  小端序:0x78 0x56 0x34 0x12
  主机字节序:本机的字节序

pack的参数:

格式字符翻译

a -- 将字符串空白以 NULL 字符填满

A -- 将字符串空白以 SPACE 字符 (空格) 填满

h -- 16进制字符串,低位在前以半字节为单位

H -- 16进制字符串,高位在前以半字节为单位

c -- 有符号字符

C -- 无符号字符

s -- 有符号短整数 (16位,主机字节序)

S -- 无符号短整数 (16位,主机字节序)

n -- 无符号短整数 (16位, 大端字节序)

v -- 无符号短整数 (16位, 小端字节序)

i -- 有符号整数 (依赖机器大小及字节序)

I -- 无符号整数 (依赖机器大小及字节序)

l -- 有符号长整数 (32位,主机字节序)

L -- 无符号长整数 (32位,主机字节序)

N -- 无符号长整数 (32位, 大端字节序)

V -- 无符号长整数 (32位, 小端字节序)

f -- 单精度浮点数 (依计算机的范围)

d -- 双精度浮点数 (依计算机的范围)

x -- 空字节

X -- 倒回一位

@ -- 填入 NULL 字符到绝对位置

关于pack和unpack推荐3篇博客,写得非常好

http://my.oschina.net/goal/blog/195749

http://my.oschina.net/goal/blog/202378

http://my.oschina.net/goal/blog/202381

后续我会结合自己项目当中php跟C模块通过Nshead协议的交互来补充这块

 

思考三:有各种数字想到了ip2long这个函数

php中的ip2long函数的原理:将每一段看成256进制的数字

function ip2int($ip) {
    list($ip1, $ip2, $ip3, $ip4) = explode(".", $ip);
    return ($ip1 << 24)  ($ip2 << 16)  ($ip3 << 8)  ($ip4);
}

问题就出现了,2int之后可能出现负数,所以我们一般使用 sprintf('%u',ip2long($ip))

php是只支持有符号的整数的,32 64的系统所支持最大的整型数是不同的,所以在不同操作系统使用ip2long的时候得到的结果可能是不一样的,这个问题值得注意

可以用sprintf('%u',ip2long($ip)),需要注意的是,sprintf返回的都是字符串

function dotip2uint($cip) {
    $dotips = explode('.', $cip, 4);
    return intval($dotips[0]) * 16216 + intval($dotips[1]) * 65536 + intval($dotips[2]) * 256 + intval($dotips[3]);
}

 

更多相关文章
一周排行