【问题标题】:How to generate card number so the users cannot follow how much is sold?如何生成卡号让用户无法跟踪销售了多少?
【发布时间】:2013-08-21 11:34:47
【问题描述】:

我想要一些生成器脚本来生成唯一的数字,但不是以一种顺序。我们需要卖票。

例如目前的票号是这样的:

100000
100001
100002
...

这样用户就可以看到卖出了多少。

如何生成唯一编号?

例如:

151647
457561
752163
...

我可以使用随机数生成器,但是如果没有生成这样的数字,我总是会检查数据库。

嗯,也许在该列上使用索引时 - 检查不会花费很长时间。

现在我还得得到最后一个卡号,如果我想给它加 1,但得到最后一个已经足够快了。

售出的门票越多,RNG 产生现有号码的机会就越大。因此,将来可能会进行更多检查。所以最好是取最后一个数字并由它生成下一个。

【问题讨论】:

标签: php numbers generator


【解决方案1】:

这是一种打乱票号的简单方法(注意:您需要 64 位 PHP,或更改代码以使用 bcmath 库):

function scramble($number) {
    return (305914*($number-100000)+151647) % 999983;
}

看,输出甚至看起来像你的例子:

Input     Output
------    ------
100000    151647
100001    457561
100002    763475
100003    069406

如果你愿意,你可以把它倒过来,这样你就可以在 URL 中使用这些代码,然后恢复原来的数字:

function unscramble($number) {
    return (605673*($number-151647)+100000) % 999983 ;
}

这样安全吗?有权访问许多序列号的人可以找到该模式,因此如果票号非常敏感,请不要使用此模式。

【讨论】:

  • 存在反函数的事实是一个提示。 999983 是一个素数,因此例如乘以任何数字 1 - 999982 模 999983 是一个双射(一对一函数)。当然,结果只是唯一的模 999983。
  • “当然,结果只是模 999983 的唯一” - 我不确定 - 这是否意味着大于此的数字 - 在编码时可能不是唯一的?
  • 所以你有超过一百万张票?有更大的素数。选择 999983 可确保您的代码永远不会超过 6 位;如果您有超过一百万个代码 6,则没有足够的 6 位数字将它们映射到。如果您想要最多 9 位的代码,您可以使用例如 999999937。
  • 一开始并没有百万票,但假设 10 年后,谁知道会卖出多少 :)
  • 那将是一个“很好的问题”,不是吗?您可以先假设不会超过 100 万张门票,如果您卖出 100 000 张门票,则开始寻找解决方案,例如使用除数字之外的字母代码。
【解决方案2】:

生成随机数,使票号唯一索引,插入新票的记录,如果失败则表示发生了冲突,因此必须生成另一个id。使用良好的随机空间,比如 32 位整数,碰撞的可能性很小。如果列是索引和数值,则后面的 SQL 实现速度非常快。

【讨论】:

    【解决方案3】:

    您可以生成您的号码,存储在一个池中,当您需要新号码时,使用该池的 RNG 索引获取一个,从池中删除并返回它。

    如果池快用完了,就再生成一批

    【讨论】:

      【解决方案4】:
       function generateCode() {
      
      
      
          $chars = '01234567890';
          do {
                  $code = '';
                  for ($x = 0; $x < 6; $x++) {
                      $code .= $chars[ rand(0, strlen($chars)-1) ];
                  }
      

      如果之前生成过此代码,您可以在数据库中查看,如果是,则返回;

        } while (true);
      
          return $code;
      
          }
      

      【讨论】:

        【解决方案5】:

        简单的方法,你可以简单地使用 md5() 函数..

        要得到一个 6 位数的字符串,你可以这样做

        $x = md5(microtime());
        
        echo substr($x, 0, 6);
        

        编辑:

        session_start();
        
            $x = md5(microtime().session_id());
        
            echo substr($x, 0, 6);
        

        【讨论】:

        • 当两个请求同时发出时,这不会导致相同的结果吗?
        • @insertusernamehere 不确定,这种可能性是否足够高?另外我编辑了我的答案。
        • 可以,但几率很小
        • 不,你正在将一个大空间映射到一个小空间,从数学上讲存在碰撞的可能性。
        • 列上的主键?
        猜你喜欢
        • 2020-08-28
        • 2014-06-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-14
        • 1970-01-01
        • 1970-01-01
        • 2021-11-16
        相关资源
        最近更新 更多