【问题标题】:Generate two random numbers between 1 to 10 using specific string使用特定字符串生成 1 到 10 之间的两个随机数
【发布时间】:2021-08-13 13:40:07
【问题描述】:

我想根据提供的字符串实现一个逻辑,我必须生成两个介于 1 到 10 之间的随机数。

我有一个像 Johnsen 这样的字符串使用它,我必须生成两个数字,例如 1 和 3,下次使用相同的字符串时,它应该为相同的字符串提供相同的数字。

需要帮助来开发此算法或逻辑。

【问题讨论】:

  • 如果它从同一个字符串产生相同的值,它不是随机的。
  • 听起来你真正想要的是hash

标签: java algorithm random numbers


【解决方案1】:

Java 通过java.util.Random 类支持随机数生成器。这个类通过有一个种子值来“工作”,然后根据这个种子值给你一些随机数据,然后将种子值更新为新的值。

这实际上意味着:

  • 如果您对其调用相同的调用序列以提供随机数据,则具有相同种子值的 2 个 j.u.Random 实例将产生相同的值序列。
  • 但是,种子值的类型为 long - 64 位数据。
  • 因此,要执行您想要的操作,您需要编写一个算法,将任何字符串转换为long
  • 鉴于这么长,您只需使用 new Random(seedValue) 构造函数创建一个带有该长作为种子的 j.u.Random 的实例。

剩下的就是:如何将字符串变成长字符串?

简单的方法

最简单的答案是在它们上调用hashCode()。但是,请注意,哈希码只有 32 位信息(它们是 int,而不是 long),所以这并没有涵盖所有可能的种子值。除非您出于加密目的这样做,否则这不太重要。如果你是,那么你需要停止你正在做的事情并做更多的研究,因为它非常容易搞砸并且有工作代码似乎可以测试,但很容易破解。你不想要那个。对于初学者,您可能需要SecureRandom,但这只是冰山一角。

更艰难的路

存在将任意数据转换为固定大小的哈希表示的哈希算法。字符串 [A] 的 hashCode 算法仅产生 32 位的哈希值,而 [B] 在密码学上不安全:如果您要求我制作一个哈希到提供值的字符串,我可以轻松做到;加密安全散列具有以下特性:我不能只为您制作一个散列到所需值的字符串。

您可以在网上搜索散列字符串或字节数组(您可以使用str.getBytes(StandardCharsets.UTF_8) 将字符串合二为一)。

您也可以很容易地将包含散列的字节数组“折叠”成一个长整数 - 只需在该散列中取出任意 8 个字节并使用它们来构造一个长整数。如果您在网上搜索“将 8 个字节转换为长”,也有大量教程。

不过,我认为简单的方法对于这个练习已经足够了。

因此:

String key = ...;
Random rnd = new Random(key.hashCode());

int number1 = rnd.nextInt(10) + 1;
int number2 = rnd.nextInt(10) + 1;

System.out.println("First number: " + number1);
System.out.println("Second number: " + number2);

【讨论】:

  • 如果您想要一个特定大小的哈希值,并且不需要加密级别的安全性,那么FNV hash 易于编码并且有多种大小。
【解决方案2】:

您可以获取字符串的哈希码,然后使用它来播种随机数生成器。使用 RNG 获取 1 - 10 范围内的数字。

【讨论】:

  • 或者只取哈希码的最后 2 位数字(每个数字加 1)。
  • @Olivier 是的,这行得通。为此目的,这些应该与 RNG 的前两个结果一样“随机”。
猜你喜欢
  • 2013-12-21
  • 2013-07-24
  • 2011-08-10
  • 1970-01-01
  • 2014-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多