Php 如何处理32位和64位服务器之间的整数最大差异?

Php 如何处理32位和64位服务器之间的整数最大差异?,php,math,32bit-64bit,uniqueidentifier,Php,Math,32bit 64bit,Uniqueidentifier,当迁移到一个更好的托管订阅时,要花很长时间才能找出导致我的网站出现故障的原因 我使用一个“自制”的uniqueId生成器生成所有必须唯一的东西,但这种唯一性不是随机的。我使用它在多个服务之间进行通信,为文件、文章等生成可复制的唯一“数字” 这是我制作的函数,从未遇到过生成唯一id的问题(我想它以前从未在64位系统上运行过?)。我知道这种唯一性是有限的(64.000),但到目前为止从未导致问题 function suGetHashCode($s) { $hash=0; $c=(is_strin

当迁移到一个更好的托管订阅时,要花很长时间才能找出导致我的网站出现故障的原因

我使用一个“自制”的uniqueId生成器生成所有必须唯一的东西,但这种唯一性不是随机的。我使用它在多个服务之间进行通信,为文件、文章等生成可复制的唯一“数字”

这是我制作的函数,从未遇到过生成唯一id的问题(我想它以前从未在64位系统上运行过?)。我知道这种唯一性是有限的(64.000),但到目前为止从未导致问题

function suGetHashCode($s)
{
 $hash=0;
 $c=(is_string($s))?strlen($s):0;
 $i=0;
 while($i<$c) 
 {
   $hash = (($hash << 5)-$hash)+ord($s{$i++});
   //hash = hash & hash; // Convert to 32bit integer
 }
 return ( $hash < 0 )?(($hash*-1)+0xFFFFFFFF):$hash; // convert to unsigned int
} 

function suUniqueId( $s, $bAddLen = false )
{ 
  $i = base_convert( suGetHashCode( $s ), 10, 32 );
  if( $bAddLen && is_string($s) )
   { $i.=('-'.suGetLz( dechex( strlen($s)*4 ), 3 )); } 

  return $i; 
}

function suGetLz( $i, $iMaxLen ) // Leading zero
{
  if( !is_numeric( $i ) || $i < 0 || $iMaxLen <= 0 )
   { return $i; }
  $c = strlen( $i );
  while( $c < $iMaxLen )
   { $c++; $i='0'.$i; } 
  return $i;
}   
在其他系统上,它是:

嗯,我不是一个数学爱好者,我认为这是造成问题的原因,因为0xFFFFFFFF增量为负值时(我认为在这个新系统上永远不会为负值)

但是我怎样才能改变函数,使其产生与其他系统相同的唯一id

例如: 它为新主机服务器上的不同字符串生成相同的id:

 $sThisUrl = '<censored>';
 var_dump( suUniqueId($sThisUrl) ); // Produce: 1l5kc37uicb  
 $sThisUrl = '<censored>';
 var_dump( suUniqueId($sThisUrl) ); // Produce the same id as above: 1l5kc37uicb
$sThisUrl='';
变量转储(suUniqueId($sthisull));//生产:1l5kc37uicb
$sThisUrl='';
变量转储(suUniqueId($sthisull));//生产与上述相同的id:1l5kc37uicb
但是,这必须与旧系统上的情况类似:

 $sThisUrl = '<censored>';
 var_dump( suUniqueId($sThisUrl) ); // Produce: a46q6nd  
 $sThisUrl = '<censored>';
 var_dump( suUniqueId($sThisUrl) ); // Produce: 2mirj1h
$sThisUrl='';
变量转储(suUniqueId($sthisull));//产品名称:a46q6nd
$sThisUrl='';
变量转储(suUniqueId($sthisull));//产量:2mirj1h
注意:字符串被分成几个部分,以避免堆栈溢出。请参见此链接

编辑:删除的文件名


有人知道如何处理这个问题吗

我建议在处理每个字符后截断:

$hash = (($hash << 5)-$hash)+ord($s{$i++});
$hash = $hash & 0xFFFFFFFF; // Convert to 32bit integer

$hash=($hash如果我是你,我会写一个单元测试,以确保你在32位和64位机器上得到相同的结果

循环应按如下方式进行更改:

while($i<$c) 
{
  $hash = (($hash << 5)-$hash)+ord($s{$i++});
  hash = hash & 0xFFFFFFFF; // Convert to 32bit integer
}
$hash = ( $hash < 0 )?(($hash*-1)+0xFFFFFFFF):$hash; // convert to unsigned int
return $hash & 0xFFFFFFFF; // Convert to 32bit integer

while($i)没有必要说“编辑:删除X”因为它只是在某种程度上吸引了人们对原始帖子的注意。你是对的,但没问题,在示例中放置两个不同的长URL,你会看到它在64位时产生相同的结果。你不能轻易收回你在sa cc许可证下发布的内容。编辑问题会使其不那么明显,但问题的原始内容是m不再是您的专有属性。此外,删除字符串会让其他人很难重现此问题。而且,由于很少有人手头上有32位和64位的PHP安装,这大大减少了比较的机会。@MvG:关键是,无论输入是什么,函数都会生成相同的id,其中的URL仅举一个例子。您可以简单地将一些不同的URL放入示例中,函数的行为保持不变。非常感谢!所有的问题都随此更改而消失。我之所以使用此方法,是因为它产生的结果不像其他哈希那样大。我不使用它来实现安全性,也不用于简单任务,有时作为校验和,有时作为id or文件标识符(temp或其他东西)和不同平台之间。再次感谢!如果这样的哈希代码的结果太长,您可以简单地参与输出,因此不再保证唯一性。…。@ta.speot.is:哈希不能保证唯一性,它们只是被设计成意外的(在加密散列的情况下,不太可能发生意外)冲突。减少冲突的大小和增加冲突的可能性,但我仍然相信截断的MD5比任何具有相同输出长度(或相同熵,更准确地说,是相同的熵,并考虑到不同的基)的自制材料更可靠。这只是一个简单的方法和一些其他方法来产生一个标识符。对我来说,它只是工作正常。我使用它可能最多40次来产生一个唯一的id的东西(在孤立的物质)。在迁移到64位之前,它从未出现过问题。如果生成的id没有问题,则没有理由正确切换?我的错误是,我在阅读您的建议时考虑了OP的唯一性要求,并将哈希与GUID混淆。与第一个答案类似,但无论如何都要感谢。此外,不需要进行否定检查,因为它运行在64位上,可以产生单词。他没有提到
$hash&0xFFFFFFFF
也没有写单元测试……实际上,他说你可以只返回$hash,但这可能会改变它的工作方式,如果你使用它一段时间,就意味着你的数据库中有依赖它的数据,所以这可能不是一个好主意我的意思是,我理解他的帖子的意思。无论如何,谢谢!你是对的,为了保持一致性,可能需要对负值进行特殊处理。愚蠢的语言,它显然有一些无符号整数的概念,但就我所知,它的语言功能不能以合理的方式处理它任何带有一个正操作数的按位and可能导致负结果的语言都应该被触发…
$hash = (($hash << 5)-$hash)+ord($s{$i++});
$hash = $hash & 0xFFFFFFFF; // Convert to 32bit integer
while($i<$c) 
{
  $hash = (($hash << 5)-$hash)+ord($s{$i++});
  hash = hash & 0xFFFFFFFF; // Convert to 32bit integer
}
$hash = ( $hash < 0 )?(($hash*-1)+0xFFFFFFFF):$hash; // convert to unsigned int
return $hash & 0xFFFFFFFF; // Convert to 32bit integer