Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/383.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Random(种子)在索引处获得Random?_Java_Random - Fatal编程技术网

Java Random(种子)在索引处获得Random?

Java Random(种子)在索引处获得Random?,java,random,Java,Random,下面的解释是我目前的代码 Random seeded = new Random(seed); for(int j = 0; j < 3; j++) { for (int i = 0; i < 10; i++) System.out.println(i + " : " + seeded.nextInt(100)); System.out.println("{}"); seeded= new Ran

下面的解释是我目前的代码

Random seeded = new Random(seed);

    for(int j = 0; j < 3; j++)
    {
        for (int i = 0; i < 10; i++)
            System.out.println(i + " : " + seeded.nextInt(100));
        System.out.println("{}");
        seeded= new Random(seed);
    }
我的目标正是上述目标。我想创建一个扩展Random的类,它包含一个GetSeedEdintaIndex函数。例如,我想实现这个类,如下所示

IndexedRandom random = new IndexedRandom(seed);
int iAt30 = random.getIntAtIndex(30);
目前,要做到这一点,我有以下代码

public int getIntAtIndex (int index)
{
    Random temp = new Random(seed);
    for(int i = 0; i < index - 1; i++)
        temp.nextInt();

    return temp.nextInt();
}
public int getIntAtIndex(int索引)
{
随机温度=新随机(种子);
对于(int i=0;i
我只是在随机X中循环多次,直到它达到所需的数量。然而,如果我选择一个大的索引,比如3000000,我更希望这个方法得到优化。有什么方法可以优化它吗?
这种方法在任何设备、PC或手机上运行只需约0.34秒。我问这个问题只是因为它看起来像是在浪费299999次计算,即使这对系统来说不是很难。如果可能的话,为什么不优化呢?

简单的回答是:不,它是一个随机函数,生成的伪随机数是前一次执行的结果,因此它仅在以相同的方式应用时产生相同的结果

但是对于您的实现,还有一些替代方案。但在优化之前,您应该验证是否确实需要优化。因为我觉得这有点像过早优化。那么,为什么您希望优化此方法?您是否已经确定了要解决的性能瓶颈?多久调用一次?优化的权衡是什么?等等

因此,假设您有很好的理由对该方法进行优化,以下是一些备选方案:

  • 根据内存限制,您可以预先填充一个完整的随机数数组并将其保存在内存中。这将需要约12 MB的内存。这可能是速度方面最有效的方法。如果经常只请求较低的值,您可以只预计算前1000个值并将其保存在内存中,然后计算高于此值的所有值。如果请求低于1000的值的频率高于请求更高的值的频率,则此方法是好的
  • 如果您从未生成3M值,但3M仅定义值范围,另一种方法是将已计算的值保留在地图中,以便您可以查找它们,而不是重新计算它们。如果请求的索引相当随机,但对同一索引多次请求相同值的概率很高,那么这种方法将是好的
  • 另一种方法是将以前的
    实例保持为随机的
    
    在地图中生成数字,然后从
    随机数开始计算仅次于请求数字的索引。比如说

    • getIntAtIndex(10)->索引<10不随机,计算10,
      map.put(10,temp)
    • getIntAtIndex(5)->索引<5不随机,计算为5,
      map.put(5,temp)
    • getIntAtIndex(7)->
      Random temp=map.remove(5)
      ,计算7,
      map.put(7,temp)
    • getIntAtIndex(12)->
      Random temp=map.remove(10)
      ,计算12,
      map.put(12,temp)
但是,如果这种方法比仅仅重新计算要慢,特别是对于较小的索引,我不会感到惊讶,因为您必须在每个请求上搜索键

实际上,
Random
的实现是基于基本运算符的,因此编译器应该能够非常有效地进行优化。因此,在采取任何行动之前,我强烈建议分析是否真的存在瓶颈


编辑

我使用索引和迭代次数的各种组合运行测试。结果是,优化是你应该做的最低限度。我花了100秒来计算我5岁的核心搭档的指数100'000的值。执行时间随索引数线性增加,影响远大于预期

这使得上面列出的所有优化都完全过时了

假设用例是,您希望给定输入值的可复制伪随机值在每次程序执行时不同,但在运行时保持不变

因此,我建议采用不同的方法。使用索引值作为种子,并通过更改计算结果的迭代次数来添加随机数。下面的代码段将生成100个程序执行的随机序列。如果需要更多随机数,请更改计算“种子”的模,但要注意,执行时间以线性方式增加。所以也许100就足够了

private long seed = System.currentTimeMillis() % 100;
public int getIntAtIndex (int index)
{
    Random temp = new Random(index);
    for(int i = 0; i < seed; i++)
        temp.nextInt();
    return temp.nextInt();
}
private long seed=System.currentTimeMillis()%100;
公共整数getIntAtIndex(整数索引)
{
随机温度=新随机(索引);
for(int i=0;i

如果游戏是这样的,你应该用一个给定的种子初始化一个随机变量,然后通过重复使用同一个随机对象来计算游戏的“开始参数”来计算所有需要的值。也就是说,如果需要100个int参数,请调用100次nextInt()。

java.util.Random
是使用以下循环来推进种子:

(seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1)
有两个原因使我没有尝试将其作为有效的Java语句编写。第一个是我们需要模幂运算来有效地计算它,第二个是我们需要80位算法来计算
(a^N-1)mod(a-1)m
。这两个问题都可以使用Java来解决,Java提供和任意精度的整数。或者,我们可以使用模幂算法的一个变体来计算
((a^N-1)mod(a-1)m)/(a-1)
作为
(a^(N-1)+a^(N-2)+…+a+1)mod m
在64位算术的范围内,从而避免了我们必须经历
biginger
的开销

Nayuki是我之前联系过的人之一,他有一个o
(seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1)
new_seed = (a^N * seed mod m) + (b * ((a^N - 1) mod (a-1)m)/(a-1) mod m)