2

我想创建一个算法来生成对象。它需要两个种子:一个硬种子(每个宇宙/每个游戏一个,在 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);
     }
  }
4

1 回答 1

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));
          }
       }
    }
    
于 2013-10-12T22:47:50.157 回答