【问题标题】:Combine World and Object Seed to Create Repeatable Random Number结合世界和对象种子创建可重复的随机数
【发布时间】:2013-10-20 18:39:34
【问题描述】:

我想创建一个算法来生成对象。它需要两个种子:一个硬种子(每个宇宙/每个游戏一个,在 ini 文件中设置)和一个“软”种子,由使用该函数的每个对象传递给函数。 (软种子属于对象,在函数调用之间不会改变)。此函数的目的是为每个对象输出一个“唯一”的随机数(0-100 之间),但可重复:每次生成对象时输出的数字都是相同的(只要保留硬种子)相同)。

在函数外部声明 Random 并使用 nextDouble() 给了我很好的分布,但意味着如果对象无序生成(这是可能的,程序将以不同的顺序生成对象),则对象将无法重复。

在函数中重新创建 Random 会给我一个糟糕的数字分布。

我的分布不均匀是因为播种/种子重量不佳吗?如何改进此功能?

以下是伪代码:我设置的一个测试类:

  public class SeedRandomTest {
    int hardSeed = 100;
    Random generator = new Random(hardSeed);
    public SeedRandomTest(){
        for (int i = 0; i < 10; i++){
            algorithmRand(i);
        }
    }

    public void algorithmRand(int seed){
        //seed would be a argument, hardseed from config properties


        int i = 0;
        int genSeed = hardSeed + seed*100;
    //      Random generator = new Random(genSeed);
        generator.setSeed(genSeed);
        double j = (generator.nextDouble() * (100));
        i = (int) j;



        System.out.println("num = "+ i);
     }
  }

【问题讨论】:

  • 你怎么知道分布不好,你是怎么测试的?
  • 我正在运行生成 10 个数字的测试程序,并且我的所有 10 个数字的“坏”分布时间都是 1:(76、74、75、73、72 等)与“好”分布一样,我得到的数字从 9 到 90 以及介于两者之间的所有数字。也许不是分布而是多样性是更好的词?编辑:我可能测试不正确并且没有喂它任何真正的种子品种,我会检查......
  • 你是对的 arynaq,我只是没有给它喂太多种类的种子。哦,天哪。好吧,谢谢你让我不再用头撞墙!
  • 您可以使用nextInt(100) 而不是nextDouble,我会将硬种子乘以质数(在初始化类时一次)并添加“软”种子。注意:在当前情况下,hardSeed = 100 和 hardSeed = 200 将具有几乎所有相同的数字,只是偏移 1。
  • 谢谢彼得!为什么我们乘以一个素数而不是仅仅使用未改变的“硬”种子?另外,你说的数字被 1 抵消是对的,你是怎么知道的?谢谢!

标签: java algorithm random seed


【解决方案1】:

假设我理解问题...

我稍微改变了你的代码结构——你不应该在构造函数中有那个 for 循环。

在一个范围内生成唯一数字的问题有两种通用方法:
(两者都会有一个种子到生成数字的映射)

(两者都提供可重复的输出。)

  • 生成 0-100,将它们洗牌。请求时返回下一个元素。

    public class SeedRandomTest
    {
       Random generator;
       List<Integer> numbers;
       Map<Integer, Integer> map;
    
       public SeedRandomTest(int hardSeed, int limit)
       {
          generator = new Random(hardSeed);
          numbers = new LinkedList<Integer>();
          map = new HashMap<Integer, Integer>();
          for (int i = 0; i <= limit; i++)
          {
             numbers.add(i);
          }
          Collections.shuffle(numbers);
       }
    
       public int algorithmRand(int seed)
       {
          /* generate a unique number for seed,
               or retrieve that number if already generated */
          if (map.containsKey(seed))
             return map.get(seed);
          int i = numbers.remove(0);
          map.put(seed, i);
          return i;
       }
    
       public static void main(String[] args)
       {
          SeedRandomTest seedRandomTest = new SeedRandomTest(89453, 100);
          for (int i = 0; i < 10; i++)
          {
             System.out.println(seedRandomTest.algorithmRand(i));
          }
       }
    }
    
  • 保留一组已经生成的数字,并在生成时生成,直到该数字不在集合中。

    这种方法的危险在于 - 如果您已经生成了大部分可用的数字,则可能需要很长时间才能找到尚未生成的数字。

    public class SeedRandomTest
    {
       Random generator;
       Set<Integer> numbers;
       Map<Integer, Integer> map;
       int limit;
    
       public SeedRandomTest(int hardSeed, int limit)
       {
          generator = new Random(hardSeed);
          numbers = new HashSet<Integer>();
          map = new HashMap<Integer, Integer>();
          this.limit = limit;
       }
    
       public int algorithmRand(int seed)
       {
          /* generate a unique number for seed,
               or retrieve that number if already generated */
          if (map.containsKey(seed))
             return map.get(seed);
          int i;
          do
          {
             i = generator.nextInt(limit+1);
          }
          while (numbers.contains(i));
          numbers.add(i);
          map.put(seed, i);
          return i;
       }
    
       public static void main(String[] args)
       {
          SeedRandomTest seedRandomTest = new SeedRandomTest(32785, 100);
          for (int i = 0; i < 10; i++)
          {
             System.out.println(seedRandomTest.algorithmRand(i));
          }
       }
    }
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-24
    • 1970-01-01
    • 1970-01-01
    • 2019-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多