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] 是种子,abc 是参数。

基于this answer,相似的种子确实在线性同余生成器中产生了相似的结果:

在给定相似种子的情况下,您会看到来自 nextDouble 的相似初始输出的原因是,因为下一个整数的计算只涉及乘法和加法,所以下一个整数的大小受低位差异的影响不大.

因此,您的两个使用默认种子连续生成的Randoms 将产生似乎相关的值并使您的山羊定位在一条线上。

要修复它,请使用相同的 Random 对象和/或比线性同余的更随机的伪随机生成器。

【讨论】:

感谢@pjs 的一些研究。

以上是关于Random() 方法有啥模式吗?的主要内容,如果未能解决你的问题,请参考以下文章

random.choices() 和 random.sample() 函数有啥区别?

numpy.random 与 numpy.random.Generate 有啥区别

random.seed():它有啥作用?

sklearn的ParameterSampler中的random_state参数有啥作用?

python tf.random_uniform与np.random_uniform有啥区别

JavaScript中Math.random()方法产生的随机数包括0和1吗?