如何把guid发散(或收敛)为32位(或64位)int

haitao 2013-06-19 04:42:47
guid据说是绝对不会重复,虽然我一直有点担心,但是基本也按这么使用了
但是有些场合,还是需要32位(或64位)int做关联,所以希望能有一个函数:
把guid发散(或收敛)为32位(或64位)int
同时,撞车的可能尽量的低
(不撞车是不可能的,128位信息缩略为32或64位,肯定有不同的guid被对应到相同的int了)
简单写了一个反复xor(顺便加点循环移位)的函数
结果,32位时,大约10万个guid就会遇到撞车了
有没有更难撞车(上千万的guid才遇到int32结果相同)的算法?
这也是一种hash算法吧
...全文
806 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
haitao 2013-06-23
  • 打赏
  • 举报
回复
引用 20 楼 u010936098 的回复:
[quote=引用 19 楼 sz_haitao 的回复:] guid转64位,估计就很难撞车了。。。。 只是bigint还是大了一点,char(22)就更大了 因为这类记录(各地的系统生成的流程模板里面的节点)的数据量总体都不会很大,希望int32能唯一就最好了
既然各地的系统数据量总体都不会很大,那么不如为每台机器分配一个唯一的16位整数作为高16位,每台机器用本地计数器生成低16位,然后合在一起。[/quote] 各个机器的用户在设计流程时,是单机离线方式,用户数也没有限制
橡木疙瘩 2013-06-23
  • 打赏
  • 举报
回复
引用 19 楼 sz_haitao 的回复:
guid转64位,估计就很难撞车了。。。。 只是bigint还是大了一点,char(22)就更大了 因为这类记录(各地的系统生成的流程模板里面的节点)的数据量总体都不会很大,希望int32能唯一就最好了
既然各地的系统数据量总体都不会很大,那么不如为每台机器分配一个唯一的16位整数作为高16位,每台机器用本地计数器生成低16位,然后合在一起。
haitao 2013-06-23
  • 打赏
  • 举报
回复
guid转64位,估计就很难撞车了。。。。 只是bigint还是大了一点,char(22)就更大了 因为这类记录(各地的系统生成的流程模板里面的节点)的数据量总体都不会很大,希望int32能唯一就最好了
橡木疙瘩 2013-06-23
  • 打赏
  • 举报
回复
引用 17 楼 sz_haitao 的回复:
系统可能在不同位置有自己的数据库,最终可能合并在一起
愣了一下才明白你是什么意思。以前我们遇到过类似的情况。在做一个项目时,我们把所有没有明显关键字的表和需要做为外键的表都设置了一个自增长字段作为主键。后来由于网络条件的限制,客户要示我们提供一些单机版的子系统,在数据采集时将数据保存到本地数据库,回来后再导入主数据库,结果在导入数据时遇到了大麻烦。 由于数据库结构不能轻易改动,最后我们专为导入数据做了很多个导入程序,将客户数据库中的数据读入内存并对象化,然后把它们当作新增对象来写入主数据库。从那以后,我们在遇到需要给表额外增加主键字段时,一概选择GUID。 想把GUID缩短长度又保持低冲突概率是很困难的,重新设计一个低冲突的随机发生器可能比它更容易。如果一定要这样做,你可以试试用DES: DES( DES(GUID[1]) xor GUID[2] ) GUID[1]和GUID[2]分别代表它的高64位和低64位。 如果数据库中有128位整数就好了,我们后来的数据表主键很多都是char(22),就是把GUID进行64进制编译后再写进数据库。
haitao 2013-06-23
  • 打赏
  • 举报
回复
引用 16 楼 u010936098 的回复:
[quote=引用 8 楼 sz_haitao 的回复:] [quote=引用 7 楼 DelphiGuy 的回复:] 你是否要求特定的GUID映射为特定的int64/int?如果不是的话可以引入某种随机量参与运算。
不太明白? 需求是把 原来用guid作为唯一性的id 的做法,改为由int32作为唯一性的id 因为不同的机器、系统可能并行地在生成guid,所以要求这些guid的对应int32也不能相同 否则靠这些int32关联就错乱了 但是guid的总个数不会太多,最多上万[/quote] 想从guid生成极难重复的int32,基本上不用考虑了。要用int32做为主键,全局计数器是最佳的办法,Oracle、SQLServer、postgresql都有相应的功能。[/quote] 系统可能在不同位置有自己的数据库,最终可能合并在一起
橡木疙瘩 2013-06-22
  • 打赏
  • 举报
回复
引用 8 楼 sz_haitao 的回复:
[quote=引用 7 楼 DelphiGuy 的回复:] 你是否要求特定的GUID映射为特定的int64/int?如果不是的话可以引入某种随机量参与运算。
不太明白? 需求是把 原来用guid作为唯一性的id 的做法,改为由int32作为唯一性的id 因为不同的机器、系统可能并行地在生成guid,所以要求这些guid的对应int32也不能相同 否则靠这些int32关联就错乱了 但是guid的总个数不会太多,最多上万[/quote] 想从guid生成极难重复的int32,基本上不用考虑了。要用int32做为主键,全局计数器是最佳的办法,Oracle、SQLServer、postgresql都有相应的功能。
  • 打赏
  • 举报
回复
引用 12 楼 sz_haitao 的回复:
谢谢 不过32位时,123497个guid里,也出现了2对撞车的: !32!{760A3509-4BFF-45EF-AF12-5CD78695F2E1}FC9DBE78 23420{25EC5239-D754-42FA-880B-0257CD626332}FC9DBE78#113472 !32!{C796FA6D-553B-45A3-8EDB-F95B87BD78B9}752BEDA8 16872{B9DC4A0E-F1E3-4916-969E-A48D73AAD9A4}752BEDA8#103241
那你用PackGUID64的低32位结果看看会不会好一些,理论上来说,洗牌粒度越小效果就越好,按word洗牌就比按dword洗输出结果分布均匀,按byte或者bit洗就更好了。 另外,14楼说的很有道理,你最好把用到的整个GUID范围,比如1000万个,都测试一下,这样才能比较出算法的好坏。
CCDDzclxy 2013-06-21
  • 打赏
  • 举报
回复
个人感觉貌似在第几个撞车是几率问题,这次 在 10万个左右出现第一个撞车,下次从头开始生成GUID时可能在1000个左右就出现第一个撞了... 应该是在某一较大范围内 出现撞车的次数基本一致,但是第一次撞车出现在何处却是不定的,和具体生成的GUID有关... 不知是否是这样,如果是这样,那就无解了...
CCDDzclxy 2013-06-21
  • 打赏
  • 举报
回复
自己写了个,无法满足楼主要求... 只能搬凳子学习了
haitao 2013-06-21
  • 打赏
  • 举报
回复
谢谢 不过32位时,123497个guid里,也出现了2对撞车的: !32!{760A3509-4BFF-45EF-AF12-5CD78695F2E1}FC9DBE78 23420{25EC5239-D754-42FA-880B-0257CD626332}FC9DBE78#113472 !32!{C796FA6D-553B-45A3-8EDB-F95B87BD78B9}752BEDA8 16872{B9DC4A0E-F1E3-4916-969E-A48D73AAD9A4}752BEDA8#103241
  • 打赏
  • 举报
回复
你试试这个: function PackGUID64(const G: TGUID): int64; asm movdqu xmm0,[eax] pshufhw xmm1,xmm0,0c9h // word order 3 0 2 1 of high 64-bit pshuflw xmm2,xmm0,72h // word order 1 3 0 2 of low 64-bit psrldq xmm1,8 psllq xmm1,1 psrlq xmm2,1 pxor xmm1,xmm2 movd eax,xmm1 psrldq xmm1,4 movd edx,xmm1 end; function PackGUID32(const G: TGUID): longint; asm movdqu xmm0,[eax] // dword order 3 2 1 0 pshufd xmm1,xmm0,39h // dword order 0 3 2 1 pshufd xmm2,xmm0,4eh // dword order 1 0 3 2 pshufd xmm3,xmm0,93h // dword order 2 1 0 3 pxor xmm0,xmm1 pxor xmm2,xmm3 psllq xmm0,1 psrlq xmm2,1 pxor xmm0,xmm2 movd eax,xmm0 end;
haitao 2013-06-20
  • 打赏
  • 举报
回复
{569022F1-D42D-48E8-B78B-E13CE069CAFF}9D57E450 {EE680DBB-33F3-412C-A80F-4B0DCE050494}9D57E450
haitao 2013-06-20
  • 打赏
  • 举报
回复
for i:=1 to SizeOf(Tguid) div SizeOf(Tint)-1 do
haitao 2013-06-20
  • 打赏
  • 举报
回复
引用 2 楼 ccrun 的回复:
{B0B21AFF-D6D9-4B50-B63D-A3519BBBC105} 用啥算法求出的 0DC25B46 ?
  CreateGUID(g);

  pb:=@g;
  p:=Pint(pb);
  d:=p^;

  for i:=1 to SizeOf(Tint)-1 do
  Begin
    inc(pb,SizeOf(Tint)); p:=Pint(pb); t:=p^;
    d:=d xor ror(t,i*3);
  End;
  s16:=Format('%.8x',[d]);
haitao 2013-06-20
  • 打赏
  • 举报
回复
每次输入某个GUID,输出的int64/int是否是固定的? 对 如果不同,就失去了对应的价值
  • 打赏
  • 举报
回复
意思是每次输入某个GUID,输出的int64/int是否是固定的?每次都是它?这种算法是多对1的关系,产生的碰撞概率大一些,如果对于输入的同一GUID,算法每次产生的输出不一定相同,碰撞的概率就小一些。
haitao 2013-06-20
  • 打赏
  • 举报
回复
引用 7 楼 DelphiGuy 的回复:
你是否要求特定的GUID映射为特定的int64/int?如果不是的话可以引入某种随机量参与运算。
不太明白? 需求是把 原来用guid作为唯一性的id 的做法,改为由int32作为唯一性的id 因为不同的机器、系统可能并行地在生成guid,所以要求这些guid的对应int32也不能相同 否则靠这些int32关联就错乱了 但是guid的总个数不会太多,最多上万
  • 打赏
  • 举报
回复
你是否要求特定的GUID映射为特定的int64/int?如果不是的话可以引入某种随机量参与运算。
sololie 2013-06-19
  • 打赏
  • 举报
回复
搬张板凳来good good study,day day up
ccrun.com 2013-06-19
  • 打赏
  • 举报
回复
{B0B21AFF-D6D9-4B50-B63D-A3519BBBC105} 用啥算法求出的 0DC25B46 ?
加载更多回复(1)

16,748

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧