如何在 Perl 中创建唯一标识符?
我正在创建一个面向文件的数据库,其中包含不同用户执行的一些测试结果。 为此,我需要为数据库中的每个条目生成唯一的 ID。 id 必须满足以下要求:
- Id 应该相当小(最多 6 个字符)
- 对于每个测试用例和用户组合,每次都应该生成相同的 id
我尝试的是一个简单的 BKDR 哈希函数,种子值为 31 并使用 ord()函数如下:
@chars = split(//,$hash_var);
$hash = 0;
$seed = 31;
foreach $char ( @chars ) {
if( $char !~ m/\d/ ) {
$hash = ( $seed * $hash ) + ord( $char );
}
else {
$hash = ( $seed * $hash ) + $char ;
}
}
$hash = ( $hash & 0x7FFFFFFF ) % 1000;
$hash = "$chars[0]$chars[$#chars]$hash" ;
这有时会导致各种组合产生相同的结果,即未观察到唯一性。 他们还有其他方法来实现这一目标吗? 改变种子价值是否有助于实现独特性?
I am creating a file-oriented database of some test results performed by various users. For this I need to generate unique id for every entry in the database. The ids must satisfy following requirements:
- Ids should be fairly small (6 characters at most)
- For every test case and user combination each time same id should be generated
What I tried was a simple BKDR hash function with seed value 31 and used ord() function as follows:
@chars = split(//,$hash_var);
$hash = 0;
$seed = 31;
foreach $char ( @chars ) {
if( $char !~ m/\d/ ) {
$hash = ( $seed * $hash ) + ord( $char );
}
else {
$hash = ( $seed * $hash ) + $char ;
}
}
$hash = ( $hash & 0x7FFFFFFF ) % 1000;
$hash = "$chars[0]$chars[$#chars]$hash" ;
This sometimes leads to same results for various combinations i.e uniqueness is not observed. Is their any other way to accomplish this? Does changing seed value help accomplish uniqueness.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您是否拥有超过 256 个用户和/或每个用户超过 65536 个测试用例? 如果没有,您可以从 0 .. 255 索引用户并从 0 .. 65535 索引测试用例,并将其编码为十六进制数字字符串,因此六个字符就可以了。
如果您有更多的用户或测试用例,我会再次索引用户和测试用例,然后将它们组合成一个 32 位整数,这实际上只需要 4 个字节,并且实现起来很简单,但对人类来说稍微困难一些。
无论如何,我假设您已获得用户名和测试用例信息。 只需保留两个绑定的哈希值:
%users
和%cases
将用户和测试用例映射到其索引号。Do you have more than 256 users and/or more than 65536 test cases per user? If not, you can just index users from 0 .. 255 and test cases from 0 .. 65535 and encode it as a string of hexadecimal digits so six characters would be fine.
If you have more users or test cases than that, I would again index the users and test cases and then combine them into a 32-bit integer which would actually only take 4 bytes and be trivial to implement but slightly harder on humans.
In any case, I am assuming you are given user name and test case information. Just keep two tied hashes:
%users
and%cases
to map users and test cases to their index numbers.您的部分问题可能是您正在使用浮点数学,而 BKDR 几乎肯定需要整数数学。 您可以通过说
另一个可能有帮助的调整是使用第一个和最后一个字符以外的字符来修复该错误。 如果第一个和最后一个字符往往相同,则它们不会为哈希添加唯一性。
您可能还想使用更好的哈希函数,例如 MD5(在 Digest::MD5 中提供)并将结果修剪为您想要的大小。 然而,您使用哈希的事实意味着您面临发生冲突的风险。
Part of your problem may be that you are using floating point math and BKDR is almost certainly wanting integer math. You can fix that bug by saying
Another tweak that might help is using characters other than the first and last. If the first and last characters tend to be the same, they add no uniqueness to the hash.
You may also want to use a better hash function like MD5 (available in Digest::MD5) and trim the result to your desired size. However, the fact that you are using a hash at all means that you run the risk of having a collision.
如果您没有很多用户/测试用例,像这样的简单解决方案可能就足够了。 您必须添加限制(并且可能在存储时打包整数)。
If you don't have a lot of users/testcases a simple solution like this might be enough. You'd have to add the limit (and probably pack the integer when storing it).