【问题标题】:Custom hash implementation for a 19-digit long19 位长的自定义哈希实现
【发布时间】:2016-07-24 01:35:06
【问题描述】:

编辑:删除了对 hashCode() 的提及

我正在开发基于种子的地形生成器,这样如果用户在文本字段中输入特定的字符串,它每次都会生成相同的世界。我计划这样做的方法是使用一种算法,该算法产生 19 位长的长度(双关语)。然后,该程序将利用某些指标的值,或某些指标的值的组合,以及其他计算来设置世界的某些方面,如生物群落、振幅和方差。本质上,只要输入相同的种子,算法就会产生相同的内部 19 位长度,从而产生相同的世界。

如何创建自定义散列方法,为每个输入值生成 19 位长?之前,我用的是这个:

private void generate() {

  long[] seedBuilder = new long[5];  // So I can print certain parts of the process for debugging purposes

  String clientSeed = seedField.getText();  // The input aka seed
  if (clientSeed.equals("")) clientSeed = String.valueOf(System.currentTimeMillis()); // use time if none is given


  // Basic hash of seed                     
  seedBuilder[0] = (long)clientSeed.hashCode();                  

  // primary-char hash * concluding-char hash (for reducing collisions)
  long comboID = clientSeed.substring(0,1).hashCode() * clientSeed.substring(clientSeed.length()-1).hashCode();                         

  // Basic hash * comboID 
  seedBuilder[1] = seedBuilder[0] * comboID; 

  // Absolute value             
  seedBuilder[2] = Math.abs(seedBuilder[1]);                     

  // Raised to the 1.27
  seedBuilder[3] = (long)(Math.pow(seedBuilder[2], 1.27));

  // Multiplied by 10.1 until digits = 19
  seedBuilder[4] = (long)(Math.pow(9.9,(19-(seedBuilder[3]+"").length())) * seedBuilder[3]);

  long generator = seedBuilder[4]

}

基本上,我通过大量实验得到了这个。 1.27的幂是任意选择的,9.9只是因为任何超过10.1的东西都可以产生Long.MAX_VALUE,但我还是想得到19位数。问题是一些蛮力随机字符串测试表明分布确实不均匀。 60% 的结果(又名 seedBuilder[4])以 3 或 4 开头,而 6 或 7 出现在第一个索引值的概率为 5%,我相信我没记错。第一个索引控制的世界的任何方面在很多时候都是相同的。

我想以一种不那么随意、更专业、更安全的方式来生成可用于生成的 19 位长度。谢谢。如果不清楚,请让我澄清一下。

【问题讨论】:

  • 错误,hashCode() 产生一个 int,而不是 long。
  • 没错,我现在修好了。

标签: java algorithm long-integer random-seed


【解决方案1】:

首先,hashCode() 返回int,而不是long,所以覆盖hashCode() 不可用。

如果您想从 String 生成 19 位(即 64 位)数值,可能最简单的方法是使用 java.security.MessageDigest 将字符串“散列”为 MD5、SHA1 或 SHA256,提取64 位并使用this StackOverflow answer 中描述的技术之一转换为long

请注意,如果不进行调整,这将返回介于 -263 和 +263-1 之间的值,因此您可能需要确保符号位处于关闭状态。然后还要注意,某些值可能不正好有 19 个十进制数字,因为结果空间包括 0 和 +263-1 之间的所有数字。在该范围中,10% 有一个或多个前导零,因此如果您总是想要 19 位数字,那么您需要保留前导零或将范围减小到 0..1018-1 并添加 1018.

【讨论】:

  • 在您提供的链接中,我可以看到一个答案,说明如何将字节转换为长整数,但我看不到如何从 MD5 中提取位。而且我不明白您所说的“将范围减小到 0..10^18-1 并添加 10^18”是什么意思。
  • 啊哈,我相信这与您所说的答案相同? stackoverflow.com/a/14420953/5484609
猜你喜欢
  • 1970-01-01
  • 2020-02-08
  • 1970-01-01
  • 2013-12-21
  • 2013-11-22
  • 2018-04-24
  • 2012-06-03
  • 2012-07-29
  • 2016-03-25
相关资源
最近更新 更多