Random() 方法有啥模式吗?
Posted
技术标签:
【中文标题】Random() 方法有啥模式吗?【英文标题】:Is there some pattern on Random() method?Random() 方法有什么模式吗? 【发布时间】:2014-11-11 16:09:10 【问题描述】:我开始制作一个有山羊的项目!是的山羊。 目前只有一个功能,当我点击一只山羊时,它会在 Random 位置创建另一只山羊。 我意识到有一种位置模式:
代码如下:
public class GameActivity extends Activity
private int[] arrGoats = new int[5];
private RelativeLayout battlefield;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
battlefield = (RelativeLayout) findViewById(R.id.rel_battlefield);
arrGoats[0] = R.drawable.amarelo;
arrGoats[1] = R.drawable.azul;
arrGoats[2] = R.drawable.branco;
arrGoats[3] = R.drawable.verde;
arrGoats[4] = R.drawable.vermelho;
criarCabra(60, 100);
private void criarCabra(float x, float y)
int cabraImg = arrGoats[new Random().nextInt(4)];
ImageView cabra = new ImageView(this);
cabra.setImageResource(cabraImg);
cabra.setX(x);
cabra.setY(y);
LayoutParams params = (LayoutParams) new LayoutParams(MarginLayoutParams.WRAP_CONTENT,
MarginLayoutParams.WRAP_CONTENT);
params.width = 150;
params.height = 120;
cabra.setLayoutParams(params);
cabra.setOnClickListener(new OnClickListener()
@Override
public void onClick(View v)
criarCabra(new Random().nextInt(2000), new Random().nextInt(1000));
);
battlefield.addView(cabra);
尽管我使用Random().NextInt()
来定义山羊的位置,但我想知道为什么会创建这种模式。
我疯了吗?
【问题讨论】:
你说的模式是什么意思? @blackbelt 看图,山羊的位置是对角线图案。 尝试在整个程序中使用 Random 的单个实例,而不是每次需要数字时都创建一个新实例。 @blackbelt 没有充分的理由创建这些立即成为垃圾回收候选对象的额外对象。 有同一个讨论***.com/questions/9726991/mathrandom-aint-so-random 【参考方案1】:您在每次调用criarCabra
和每次调用onClick
时都会创建Random
的新实例。创建Random
的单个静态实例,然后重新使用它。
除非您真的知道自己在做什么并且有充分的理由这样做,否则最佳做法是只为每个程序创建一个 Random
实例,然后在您需要其他值时轮询它。
【讨论】:
等待回复:D ... 创建一个新的随机对象将如何导致 OP 看到的行为? @laalto 通过与播种机制的交互。 Java 的Random
是一个线性同余生成器,当种子顺序相关时,那些臭名昭著的生成器会产生共线结果。请参阅 LCG Wikipedia page 上对 Marsaglia 定理的简要讨论。【参考方案2】:
首先,您每次都创建一个新的Random
对象。在 android 中,initial seed is derived from current time and the identity hash code:
public Random()
// Note: Using identityHashCode() to be hermetic wrt subclasses.
setSeed(System.currentTimeMillis() + System.identityHashCode(this));
对于按顺序创建的两个对象,身份哈希码彼此接近。在我的 Android KitKat Dalvik VM 上,我得到的身份哈希码仅相差 32。
currentTimeMillis()
对种子也没有太大区别。
随机数本身就是linear congruential generator的形式
random[i+1] = a * random[i] + b (mod c)
其中random[0]
是种子,a
、b
和c
是参数。
基于this answer,相似的种子确实在线性同余生成器中产生了相似的结果:
在给定相似种子的情况下,您会看到来自 nextDouble 的相似初始输出的原因是,因为下一个整数的计算只涉及乘法和加法,所以下一个整数的大小受低位差异的影响不大.
因此,您的两个使用默认种子连续生成的Random
s 将产生似乎相关的值并使您的山羊定位在一条线上。
要修复它,请使用相同的 Random
对象和/或比线性同余的更随机的伪随机生成器。
【讨论】:
感谢@pjs 的一些研究。以上是关于Random() 方法有啥模式吗?的主要内容,如果未能解决你的问题,请参考以下文章
random.choices() 和 random.sample() 函数有啥区别?
numpy.random 与 numpy.random.Generate 有啥区别
sklearn的ParameterSampler中的random_state参数有啥作用?