19 位长的自定义哈希实现
Custom hash implementation for a 19-digit long
编辑:删除了对 hashCode()
的提及
我正在研究基于种子的地形生成器,这样如果用户在文本字段中输入特定的字符串,它每次都会生成相同的世界。我计划这样做的方法是使用一种算法来生成 19 位长的 long(双关语意)。然后,该程序将利用某些指标的值,或某些指标的值的组合,以及其他计算来设置世界的某些方面,如生物群落、振幅和方差。本质上,无论何时输入相同的种子,算法都会产生相同的内部 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()
returns int
,而不是 long
,所以重写 hashCode()
是不可能的。
如果要从 String
生成 19 位(即 64 位)数值,可能最简单的方法是使用 java.security.MessageDigest
到 "hash" 字符串到 MD5、SHA1 或 SHA256,提取 64 位并使用 this Whosebug answer 中描述的技术之一转换为 long
。
请注意,如果不进行调整,这个 returns 的值介于 -263 和 +263-1 之间,因此您可能要确保符号位关闭。然后还要注意,某些值可能没有正好 19 位十进制数字,因为结果 space 然后包括 0 和 +263-1 之间的所有数字。在该范围中,10% 有一个或多个前导零,因此如果您总是想要 19 位数字,那么您将需要保留前导零或将范围缩小到 0..1018-1 和添加 1018.
编辑:删除了对 hashCode()
的提及我正在研究基于种子的地形生成器,这样如果用户在文本字段中输入特定的字符串,它每次都会生成相同的世界。我计划这样做的方法是使用一种算法来生成 19 位长的 long(双关语意)。然后,该程序将利用某些指标的值,或某些指标的值的组合,以及其他计算来设置世界的某些方面,如生物群落、振幅和方差。本质上,无论何时输入相同的种子,算法都会产生相同的内部 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()
returns int
,而不是 long
,所以重写 hashCode()
是不可能的。
如果要从 String
生成 19 位(即 64 位)数值,可能最简单的方法是使用 java.security.MessageDigest
到 "hash" 字符串到 MD5、SHA1 或 SHA256,提取 64 位并使用 this Whosebug answer 中描述的技术之一转换为 long
。
请注意,如果不进行调整,这个 returns 的值介于 -263 和 +263-1 之间,因此您可能要确保符号位关闭。然后还要注意,某些值可能没有正好 19 位十进制数字,因为结果 space 然后包括 0 和 +263-1 之间的所有数字。在该范围中,10% 有一个或多个前导零,因此如果您总是想要 19 位数字,那么您将需要保留前导零或将范围缩小到 0..1018-1 和添加 1018.