简体   繁体   English

Math.random()使用安全吗?

[英]Is Math.random() safe to use?

I have a method which is generating random integers. 我有一个生成随机整数的方法。 I don't want integers to be repeated, so I created this code - 我不想重复整数,所以我创建了这段代码-

int prevInt = 0;

private int randomInt() {
    int random = (int) (Math.random() * 3);
    //generate random numbers between 0 to 3 inclusive

    if(random == prevInt)
        return randomInt();
    //if previous random number is equal to currently generated
    //random number, then call this method again for a different
    //random number

    prevInt = random;
    return random;
    //else return the generated random number
}

Is the above code safe to use? 上面的代码安全使用吗? At worst case scenario, can it be possible that all random integers generated by Math.random() * 3 are same? 在最坏的情况下,由Math.random() * 3生成的所有随机整数是否可能都相同?

private final Random random = new Random();

private int randomInt(final int prev, final int max) {
  final int next = random.nextInt(max - 1);
  if(next >= prev){
    return next + 1;
  }else{
    return next;
  }
}

This will return an int between 0 and max without the need to repeat. 这将返回一个介于0和max之间的int,而无需重复。

public static double random()

Returns a double value with a positive sign , greater than or equal to 0.0 and less than 1.0. 返回一个带正号精度值,大于或等于0.0且小于1.0。 Returned values are chosen pseudorandomly with (approximately) uniform distribution from that range. 从该范围(近似)均匀分布伪随机地选择返回值。

There are two principal means of generating random (really pseudo-random) numbers: 生成随机 (真正的伪随机)数有两种主要方法

  1. the Random class generates random integers, doubles, longs and so on, in various ranges. Random类生成各种范围内的随机整数,双精度数,长整型等。

  2. the static method Math.random generates doubles between 0 (inclusive) and 1 (exclusive). 静态方法Math.random生成介于0(含)和1(不含)之间的双精度值。

To generate random integers: 生成随机整数:

do not use Math.random (it produces doubles, not integers) use the Random class to generate random integers between 0 and N. To generate a series of random numbers as a unit, you need to use a single Random object - do not create a new Random object for each new random number. 不要使用Math.random (它会生成双精度数,而不是整数),请使用Random类来生成0到N之间的随机整数。要生成一系列作为单元的随机数,您需要使用单个Random对象-不要创建每个新的随机数都有一个新的Random对象。

Other alternatives are: 其他替代方法是:

SecureRandom, a cryptographically strong subclass of Random
ThreadLocalRandom, intended for multi-threaded cases

please have a look at this post. 请看看这篇文章。 SO Reference 1 , Reference 2 SO参考1参考2

From the javadoc, Math.random() return a pseudo random and (approximately) uniform distributed number within the range. 从javadoc中, Math.random()返回该范围内的伪随机数和(近似)均匀分布数。

So when you don't strict accuracy you may use it. 因此,当您不严格要求准确性时,可以使用它。 Otherwise search for better solution. 否则,寻求更好的解决方案。

try this trivial code and see for yourself 试试这个琐碎的代码,自己看看

    for (int ran = 0; ran < 10; ran++) {
        int random = (int) (Math.random() * 3);
        System.out.println(random);
    }

Output in my case 就我而言

2 2 0 2 1 0 0 0 2 1 2 2 0 2 1 0 0 0 2 1

是的,它很安全,但是我们永远不知道会发生什么,因此我们可以简单地将Math.random乘以两次以保持良好的安全性

int random = (int) (Math.random() * Math.random() * 3);

First, I must point that your question title is not that clear. 首先,我必须指出,您的问题标题不清楚。 Safe can mean various thing. 安全可能意味着各种事情。 In this case I think you mean safety of algorithm of your code, not security nor only Math.random(). 在这种情况下,我认为您是指代码算法的安全性,而不是安全性,也不是Math.random()。

Unfortunately, your code is not algorithmically safe. 不幸的是,您的代码在算法上并不安全。 Even if Math.random is safe, Your code has always positive possibility on running at any time: roughly speaking it means there are no guarantee that your code ends in finite time. 即使Math.random是安全的,您的代码也始终可以随时运行:粗略地说,这意味着无法保证您的代码在有限的时间内结束。

Assume you are taking random number among 4 numbers. 假设您正在4个数字中取随机数。 If you are drawing random number excluding right before number, you're actually not drawing from 4 numbers: it's 3. I suggest another method: 如果您要绘制随机数( 不包括数字前的数字),则实际上不是从4个数字中绘制:是3。我建议另一种方法:

int prevInt = -1;

private int randomInt() {
    if (prevInt == -1) {
        int random = (int) (Math.random() * 4);
        //generate random numbers between 0 to 3 inclusive
    } else if
        int random = (int) (Math.random() * 3);
        random = (random >= prevint) ? (random + 1) % 4 : random;
    }

    prevInt = random;
    return random;
}

private void resetRandom() {
    prevInt = -1;
    //use when you want to reset information that you have 'before' result.
}

This algorithm ends within finite time. 该算法在有限时间内结束。 Concern about whether Math.Random() itself is dangerous or whatever will be explained by other nice guys. 担心Math.Random()本身是否很危险,或者其他好家伙会解释什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM