LibGDX 对 MathUtils.random() 的内部调用会干扰生成的随机数序列
LibGDX internal calls to MathUtils.random() interfere with the sequence of random numbers generated
在多次使用给定种子的随机数生成器 (RNG) 时(即每次调用 setSeed()
使用相同的种子重新开始),我在数字序列中遇到了一些偏差在每次通过时生成。用头撞墙几次后发现原因是这样的:
box2d
的 World.createBody()
调用 LongMap.put()
,后者调用 LongMap.push()
,后者在 while
循环中调用 MathUtils.random()
。
据我所知,粒子效果也会调用 MathUtils.random()
。
那么,如果 LibGDX 在内部使用相同的静态 RNG 实例,那么我怎么能相信数字序列总是重复自己,因此可能会弄乱序列?
我怎么才能确切知道 MathUtils.random()
在我的代码之外被调用的确切位置和时间?
如@Peter R 所述,可以创建自己的 RNG,保证不会干扰数字序列。
可以使用Java的Random:
import java.util.Random;
private Random random = new Random();
或 MathUtils 使用的 RandomXS128(它扩展了 Java 的 Random 但速度更快):
import com.badlogic.gdx.math.RandomXS128;
private Random random = new RandomXS128();
MathUtils 中方便的包装方法(random() 签名)也可以根据需要使用(复制到自己的 class),无论是否是静态的。例如:
/** Returns a random number between start (inclusive) and end (inclusive). */
public int random (int start, int end) {
return start + random.nextInt(end - start + 1);
}
/** Returns a random number between start (inclusive) and end (exclusive). */
public float random (float start, float end) {
return start + random.nextFloat() * (end - start);
}
就我自己而言,我仍然对为什么 MathUtils 提供一个共享的 RNG 以供内部和外部使用感到困惑,这使得它与种子一起使用是不安全的,并且在评论中没有提到这一点。
但是上面的解决方法对于任何不像我这样小气的人来说应该是令人满意的。
在多次使用给定种子的随机数生成器 (RNG) 时(即每次调用 setSeed()
使用相同的种子重新开始),我在数字序列中遇到了一些偏差在每次通过时生成。用头撞墙几次后发现原因是这样的:
box2d
的 World.createBody()
调用 LongMap.put()
,后者调用 LongMap.push()
,后者在 while
循环中调用 MathUtils.random()
。
据我所知,粒子效果也会调用 MathUtils.random()
。
那么,如果 LibGDX 在内部使用相同的静态 RNG 实例,那么我怎么能相信数字序列总是重复自己,因此可能会弄乱序列?
我怎么才能确切知道 MathUtils.random()
在我的代码之外被调用的确切位置和时间?
如@Peter R 所述,可以创建自己的 RNG,保证不会干扰数字序列。
可以使用Java的Random:
import java.util.Random;
private Random random = new Random();
或 MathUtils 使用的 RandomXS128(它扩展了 Java 的 Random 但速度更快):
import com.badlogic.gdx.math.RandomXS128;
private Random random = new RandomXS128();
MathUtils 中方便的包装方法(random() 签名)也可以根据需要使用(复制到自己的 class),无论是否是静态的。例如:
/** Returns a random number between start (inclusive) and end (inclusive). */
public int random (int start, int end) {
return start + random.nextInt(end - start + 1);
}
/** Returns a random number between start (inclusive) and end (exclusive). */
public float random (float start, float end) {
return start + random.nextFloat() * (end - start);
}
就我自己而言,我仍然对为什么 MathUtils 提供一个共享的 RNG 以供内部和外部使用感到困惑,这使得它与种子一起使用是不安全的,并且在评论中没有提到这一点。
但是上面的解决方法对于任何不像我这样小气的人来说应该是令人满意的。