Generate Random numbers without using any external functions

后端 未结 9 972
梦如初夏
梦如初夏 2020-12-08 16:26

This was questions asked in one of the interviews that I recently attended.

As far as I know a random number between two numbers can be generated as follows

相关标签:
9条回答
  • 2020-12-08 16:31

    Does System.currentTimeMillis() count as external? You could always get this and calculate mod by some max value:

    int rand = (int)(System.currentTimeMillis()%high)+low;
    
    0 讨论(0)
  • 2020-12-08 16:39
    public class randomNumberGenerator {
    
        int generateRandomNumber(int min, int max) {
            return (int) ((System.currentTimeMillis() % max) + min);
        }
    
        public static void main(String[] args) {
            randomNumberGenerator rn = new randomNumberGenerator();
            int cv = 0;
            int min = 1, max = 4;
            Map<Integer, Integer> hmap = new HashMap<Integer, Integer>();
    
            int count = min;
            while (count <= max) {
                cv = rn.generateRandomNumber(min, max);
                if ((hmap.get(cv) == null) && cv >= min && cv <= max) {
                    System.out.print(cv + ",");
                    hmap.put(cv, 1);
                    count++;
                }
            }
    
        }
    }
    
    0 讨论(0)
  • 2020-12-08 16:40

    You can do it without external functions if you are allowed to use some external state (e.g. a long initialised with the current system time). This is enough for you to implement a simple psuedo-random number generator.

    In each call to your random function, you would use the state to create a new random value, and update the state, so that subsequent calls get different results.

    You can do this with just regular Java arithmetic and/or bitwise operations, so no external functions are required.

    0 讨论(0)
  • 2020-12-08 16:40

    Poisson Random Generator

    Lets say we start with an expected value 'v' of the random numbers. Then to say that a sequence of non negative integers satisfies a Poisson Distribution with expected value v means that over subsequences, the mean(average) of the value will appear 'v'. Poisson Distribution is part of statistics and the details can be found on wikipedia. But here the main advantage of using this function are: 1. Only integer values are generated. 2. The mean of those integers will be equal to the value we initially provided.

    It is helpful in applications where fractional values don't make sense. Like number of planes arriving on an airport in 1min is 2.5(doesn't make sense) but it implies that in 2 mins 5 plans arrive.

    int poissonRandom(double expectedValue) {
      int n = 0; //counter of iteration
      double limit; 
      double x;  //pseudo random number
      limit = exp(-expectedValue);
      x = rand() / INT_MAX; 
      while (x > limit) {
        n++;
        x *= rand() / INT_MAX;
      }
      return n;
    }
    

    The line

    rand() / INT_MAX
    

    should generate a random number between 0 and 1. So we can use time of the system. Seconds / 60 will serve the purpose. Which function we should use is totally application dependent.

    0 讨论(0)
  • 2020-12-08 16:42

    Typical pseudo-random number generators calculate new numbers based on previous ones, so in theory they are completely deterministic. The only randomness is guaranteed by providing a good seed (initialization of the random number generation algorithm). As long as the random numbers aren't very security critical (this would require "real" random numbers), such a recursive random number generator often satisfies the needs.

    The recursive generation can be expressed without any "external" functions, once a seed was provided. There are a couple of algorithms solving this problem. A good example is the Linear Congruential Generator.

    A pseudo-code implementation might look like the following:

    long a = 25214903917;   // These Values for a and c are the actual values found
    long c = 11;            // in the implementation of java.util.Random(), see link
    long previous = 0;
    
    void rseed(long seed) {
        previous = seed;
    }
    
    long rand() {
        long r = a * previous + c;
        // Note: typically, one chooses only a couple of bits of this value, see link
        previous = r;
        return r;
    }
    

    You still need to seed this generator with some initial value. This can be done by doing one of the following:

    • Using something like the current time (good in most non-security-critical cases like games)
    • Using hardware noise (good for security-critical randomness)
    • Using a constant number (good for debugging, since you get always the same sequence)
    • If you can't use any function and don't want to use a constant seed, and if you are using a language which allows this, you could also use some uninitialized memory. In C and C++ for example, define a new variable, don't assign something to it and use its value to seed the generator. But note that this is far from being a "good seed" and only a hack to fulfill your requirements. Never use this in real code.

    Note that there is no algorithm which can generate different values for different runs with the same inputs without access to some external sources like the system environment. Every well-seeded random number generator makes use of some external sources.

    0 讨论(0)
  • 2020-12-08 16:48

    You can get near randomness (actually chaotic and definitely not uniform*) from the logistic map x = 4x(1-x) starting with a "non-rational" x between 0 and 1.

    The "randomness" appears because of the rounding errors at the edge of the accuracy of the floating point representation.

    (*)You can undo the skewing once you know it is there.

    0 讨论(0)
提交回复
热议问题