人类可读订单代码的完美哈希函数

2024-03-12

我正在尝试生成从(比方说)无符号 32 位内部 ID 派生的非连续人类可读订单代码,该 ID 从 1 开始,并针对每个新订单自动递增。

在下面的示例代码中,每个$hash是独一无二的吗? (我计划对$hash使其易于人类阅读。)

<?php
function int_hash($key) {
  $key = ($key^0x47cb8a8c) ^ ($key<<12);
  $key = ($key^0x61a988bc) ^ ($key>>19);
  $key = ($key^0x78d2a3c8) ^ ($key<<5);
  $key = ($key^0x5972b1be) ^ ($key<<9);
  $key = ($key^0x2ea72dfe) ^ ($key<<3);
  $key = ($key^0x5ff1057d) ^ ($key>>16);
  return $key;
}

for($order_id = 1; $order_id <= PHP_INT_MAX; ++$order_id) {
  $hash = int_hash($order_id);
}
?>

如果没有,是否有关于如何更换的建议int_hash?

比如说,base34 编码的结果md5($order_id)对我来说太长了。


在下面的示例代码中,每个$hash是独一无二的吗?

Almost.(我猜,这意味着“不,但是以一种很容易修复的方式”。)您的函数由一系列独立的步骤组成;当且仅当这些步骤中的每一步都是双射的(可逆的)时,整体函数才是双射的(可逆的)。 (你明白为什么吗?)

现在,每个步骤都具有以下形式之一:

  $key = ($key ^ CONSTANT) ^ ($key >> NUM_BITS);
  $key = ($key ^ CONSTANT) ^ ($key << NUM_BITS);

with NUM_BITS != 0.

我们实际上可以将它们视为单一形式的变体,将前者视为almost相当于这个:

  $key = invert_order_of_bits($key); # clearly bijective
  $constant = invert_order_of_bits(CONSTANT);
  $key = ($key ^ $constant) ^ ($key << NUM_BITS);
  $key = invert_order_of_bits($key); # clearly bijective

所以我们需要做的就是证明这一点:

  $key = ($key ^ CONSTANT) ^ ($key << NUM_BITS);

是双射的。现在,XOR 是可交换和结合的,所以上面等价于:

  $key = $key ^ ($key << NUM_BITS);
  $key = $key ^ CONSTANT;

and (x ^ y) ^ y == x ^ (y ^ y) == x ^ 0 == x,因此显然与常量值进行异或运算是可逆的(通过与相同值重新进行异或运算);所以我们必须证明这是双射的:

  $key = $key ^ ($key << NUM_BITS);

每当NUM_BITS != 0.

现在,我没有写出严格的证明,所以我只是给出一个single如何扭转这种情况的合理示例。假设$key ^ ($key << 9) is

0010 1010 1101 1110 0010 0101 0000 1100

我们如何获得$key?嗯,我们知道最后九位$key << 9都是零,所以我们知道最后九位$key ^ ($key << 9)与最后九位相同$key. So $key好像

bbbb bbbb bbbb bbbb bbbb bbb1 0000 1100

so $key << 9好像

bbbb bbbb bbbb bb10 0001 1000 0000 0000

so $key好像

bbbb bbbb bbbb bb00 0011 1101 0000 1100

(通过异或运算$key ^ ($key << 9) with $key << 9), so $key << 9好像

bbbb b000 0111 1010 0001 1000 0000 0000

so $key好像

bbbb b010 1010 0100 0011 1101 0000 1100

so $key << 9好像

0101 1000 0111 1010 0001 1000 0000 0000

so $key好像

0111 0010 1010 0100 0011 1101 0000 1100

所以 。 。 。为什么我说“几乎”而不是“是”?为什么你的哈希函数不是完美双射?这是因为在 PHP 中,按位移位运算符>> and <<不是quite对称,同时$key = $key ^ ($key << NUM_BITS)是完全可逆的,$key = $key ^ ($key >> NUM_BITS)不是。 (在上面,当我写到这两种类型的步骤是“almost等价”,我真的meant那个“几乎”。这很重要!)你看,而<<像对待任何其他位一样对待符号位,并将其移出(在右侧引入零位),>>特别对待符号位,并“扩展”它:它在左侧引入的位等于符号位。 (注意:您的问题提到“无符号 32 位”值,但 PHP 实际上并不支持该值;它的按位运算始终处于开启状态signed整数。)

由于这个符号扩展,如果$key以一个开头0, then $key >> NUM_BITS以一个开头0, 而如果$key以一个开头1, then $key >> NUM_BITS也以一个开头1。在任一情况下,$key ^ ($key >> NUM_BITS)将从0。你已经损失了一点点熵。如果你给我$key ^ ($key >> 9),并且不要告诉我是否$key是负数,那么我能做的最好的就是计算两个可能的值$key:一个负值,一个正值或零。

您执行两个使用右移而不是左移的步骤,因此您丢失了两位熵。 (我轻轻挥手——我实际上证明的是你输了at least一位和at most两位 - 但我相信,由于这些右移步骤之间的步骤的性质,您实际上会丢失两个完整位。)对于任何给定的输出值,恰好有四个不同的输入值可以产生它。所以它不是唯一的,但它是almost独特的;并且可以通过以下任一方法轻松修复:

  • 将两个右移步骤更改为使用左移;或者
  • moving both of the right-shift steps to the start of the function, before any left-shift steps, and saying that outputs are unique for inputs between 0 and 231−1 rather than inputs between 0 and 232−1.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

人类可读订单代码的完美哈希函数 的相关文章

  • 哈希上的多次迭代:这不会减少熵吗?

    我看到在很多地方 包括堆栈 都推荐了这种技术 而且我无法摆脱这种技术会减少熵 毕竟 您正在再次对已经被散列过并且有碰撞机会的东西进行散列 碰撞机会大于碰撞机会会不会导致更多的碰撞机会 经过研究 似乎我错了 但为什么呢 既然您标记了 md5
  • 使用 MYSQL 将 h:mm pm/am 时间格式插入数据库

    我正在尝试将以 h mm am pm 格式写入的时间插入到存储为标准 DATETIME 格式 hh mm ss 的数据库中 但我不知道如何将发布的时间转换为标准格式所以数据库会接受它 这是我到目前为止一直在尝试的 title POST in
  • if/else 简写来定义变量

    我很难理解 if else 的 php 简写是如何描述的here https stackoverflow com questions 20233207 php if shorthand and echo in one line possib
  • 禁用 WooCommerce 手动/编辑订单的电子邮件通知

    需要 WooCommerce 专业知识 我需要禁用手动创建的订单的电子邮件通知 我必须使用处理状态 由于处理订单状态的自定义挂钩 我无法创建自定义状态 理想情况下 手动订单页面中可以勾选一个复选框 勾选后 它将禁止在每种状态下向客户发送电子
  • 所有 PHP 相等比较都是对称的吗?

    Is a b总是等价于 b a 我认为在 JavaScript 中 由于强制转换 有一些奇怪的情况并非如此 I think ide https stackoverflow com questions 4752579 are all php
  • Smarty 如果 URL 包含

    使用 Smarty 标签我想确定 URL 是否包含单词 例如 if smarty get page contains product php 我知道 contains 不存在 但是我怎样才能轻松地编写类似的东西来实现上述代码呢 所有 PHP
  • 防止 Propel 插入空字符串

    当未设置列时 如何防止 Propel ORM 插入空字符串 CREATE TABLE user uid INTEGER PRIMARY KEY AUTO INCREMENT email VARCHAR 255 NOT NULL UNIQUE
  • 简单的 PHP 回显代码不起作用

    这是我的 html 和 php 脚本 h1 Bob s Auto Parts h1 table width 100 tr tr table 为什么这个输出会出现一个 gt 我希望它是 这有效 仅有的 这是输出 鲍勃的汽车零件 鲍勃
  • Google Cloud SQL 上的故障转移如何运作?

    我打算将 PHP 应用程序 从 Google Cloud Platform 外部的服务器 连接到 Google Cloud SQL 我想知道如何设计应用程序以正确地对其数据库进行故障转移 根据manual https cloud googl
  • PHP - 类外 use 关键字和类内 use 关键字的区别

    伙计们 美好的一天 只是想问一下有什么区别use之外的class and use在 的里面class 我也用谷歌搜索过 但我的问题与答案不匹配 Example namespace App Http Controllers Auth use
  • 获取字符串中的最后一个整数

    我需要隔离包含多个整数的字符串中最新出现的整数 我怎样才能得到23代替1 for lastnum1 text 1 out of 23 lastnum1 this gt getEval eregi replace out of text 你可
  • 在 WooCommerce 中添加到购物车之前清空购物车

    我正在使用 WP 作业管理器和 Woo Subscriptions Now 最初 我选择了一个套餐 Woo Subscription 然后我添加了所有细节 但没有提交 回到网站 所以要再次购买 我需要选择一个套餐 于是我选择了套餐并填写了详
  • Facebook 应用程序无法获取会话

    我正在 Heroku 上为 Facebook 开发一个非常基本的 PHP 应用程序 它显示非常基本的用户信息 如姓名 个人资料图片 但该应用程序在 getToken 方法中停止 我在登录我的个人资料后尝试了该应用程序 但仍然出现相同的消息
  • 在 Yii 的标准中如何获得计数 (*)

    我正在尝试构建一个具有以下内容的查询group by属性 我正在尝试得到id和count它一直告诉我count is invalid列名 我怎样才能得到count来自group by询问 工作有别名 伊伊 1 1 11 其他不及格 crit
  • 如何在 Zend MVC 中实现 SSL

    我之前已经通过使用特定的安全文件夹 例如服务器上的 https 文件夹与 http 文件夹 实现了安全页面 我已经开始使用 Zend Framework 并希望应用程序的某些部分 例如登录 使用 https 我在谷歌上搜索过 甚至在这里搜索
  • Facebook PHP SDK - 如何获取访问令牌?

    我正在尝试从我的应用程序在用户的 Facebook 墙上发帖 用户授予应用程序在他的墙上发布的权限 并且我在数据库中有用户ID 我需要自动发送帖子 而无需用户再次登录 我的代码是 try require once dirname FILE
  • PHP print_r() 中 _r 的含义是什么?

    我见过这个答案 https stackoverflow com questions 13103410 what does r suffix mean就这样 但我不确定它对于 PHP 是否相同 如果是 可重入的含义是什么 From PHP n
  • 使用 json_encode() 函数在 PHP 数组中生成 JSON 键值对

    我正在尝试以特定语法获取 JSON 输出 这是我的代码 ss array 1 jpg 2 jpg dates array eu gt 59 99 us gt 39 99 array1 array name gt game1 publishe
  • 从所有会话中注销

    我有一个注销选项 这是我的代码 session start session destroy setcookie key time 60 60 24 setcookie username time 60 60 24 我想添加另一个选项来注销所
  • 使用 crypt() 加密

    我目前正在做一个非常安全的登录系统 但我是 crypt 函数的新手 需要一些快速帮助 我在注册过程中使用 crypt 加密密码字符串并将其保存到数据库中 但是 我如何在登录过程中解密密钥 或者我应该怎么做 或者是否可以对提交的密码字符串进行

随机推荐