19

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

public static int rand(int low, int high) {
    return low + (int)(Math.random() * (high - low + 1));
}

But here I am using Math.random() to generate a random number between 0 and 1 and using that to help me generate between low and high. Is there any other way I can directly do without using external functions?

Usha
  • 374
  • 1
  • 5
  • 14
  • 2
    So what is your source of randomness, then? Most programs will be completely deterministic if you can't use any external functions. – Andrew Mao Feb 23 '13 at 07:21
  • 1
    Can you clarify what exactly makes a function 'external'? Math is a pretty basic class in java.. – Krease Feb 23 '13 at 07:21
  • 3
    @AndrewMao, even the library functions are completely deterministic. They simulate a random sequence without actually being one. Your only hope of getting something truly random is to rely on an external source of randomness. – Mark Ransom Feb 23 '13 at 07:39
  • What do you call external function? If functions from programming language are external for you, then what isn't external? – Danubian Sailor Feb 23 '13 at 15:32
  • @MarkRansom I totally agree with you, but I'm talking about Java's random setting the seed from `System.currentTimeMillis()`, or something like that. Otherwise, you will get the same initial random number every time. – Andrew Mao Feb 23 '13 at 15:50

9 Answers9

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.

leemes
  • 44,967
  • 21
  • 135
  • 183
  • 1
    Also note that Linear Congruential Generators are considered kind of crude these days, there are better alternatives (though none simpler). – Mark Ransom Feb 23 '13 at 07:41
  • @MarkRansom Yeah, I wanted to explain the generator algorithm most easy to understand which isn't too bad. Also, it's the RNG found in java.util.Random, so it's near the OP's code. (However, I don't know how Math.random is different from this one.) – leemes Feb 23 '13 at 07:44
  • +1 for good explanation, but for clarification Random is related to the series it generate, not how it was generated – Khaled.K Apr 05 '13 at 13:10
  • !not important but declare long a = 25214903917; as long a = 25214903917L; – dhanu10896 Feb 03 '19 at 07:55
7

Here I am suggesting some sources with comment may be you find helpful:

  • System Time : Monotonic in a day poor random. Fast, Easy.
  • Mouse Point : Random But not useful on standalone system.
  • Raw Socket/ Local Network (Packet 's info-part ) : Good Random Technical and time consuming - Possible to model a attack mode to reduce randomness.
  • Some input text with permutation : Fast, Common way and good too (in my opinion).
  • Timing of the Interrupt due to keyboard, disk-drive and other events: Common way – error prone if not used carefully.
  • Another approach is to feed an analog noise signal : example like temp.
  • /proc file data: On Linux system. I feel you should use this.

    /proc/sys/kernel/random: This directory contains various parameters controlling the operation of the file /dev/random.

    The character special files /dev/random and /dev/urandom (present since Linux 1.3.30) provide an interface to the kernel's random number generator.

    try this commads:

    $cat /dev/urandom   
    

    and

    $cat /dev/random
    

    You can write a file read function that read from this file.

    Read (also suggests): Is a rand from /dev/urandom secure for a login key?

`

Community
  • 1
  • 1
Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
5

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;
Krease
  • 15,805
  • 8
  • 54
  • 86
  • 6
    Chris: Worst bug of my life came from depending on this. I instantiated 2 random classes (silly me). When running normally, they produced the same values screwing up my logic. This is because the time was used as a seed, and they ran within 1 millisecond of each other. However, this didn't occur when debugging, because the time seeds were different. Took me a long time to find why the app worked in debug mode but not normally! – Peter Webb Feb 24 '13 at 06:29
2

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.

Mark Hurd
  • 10,665
  • 10
  • 68
  • 101
0

You may use the address of a variable or combine the address of more variables to make a more complex one...

Alireza Soori
  • 645
  • 9
  • 25
  • 4
    That has a high chance to be predictable/contiguous/repeatable. – Tim M. Feb 23 '13 at 07:24
  • and there's many ways that you can do so like converting the address string to a simple int var or use the numbers only or adding multiple address then use the result , etc.... – Alireza Soori Feb 23 '13 at 07:26
  • 1
    http://stackoverflow.com/questions/1961146/memory-address-of-variables-in-java this question is about addresses in java the rest of the algorithm is easy i guess – Alireza Soori Feb 23 '13 at 07:28
0

You could get the current system time, but that would also require a function in most languages.

user000001
  • 32,226
  • 12
  • 81
  • 108
0

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.

mikera
  • 105,238
  • 25
  • 256
  • 415
-2
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++;
            }
        }

    }
}
Guillaume S
  • 1,462
  • 2
  • 19
  • 31
-3

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.

SureshS
  • 589
  • 8
  • 23
  • I suppose "no external functions" is for any random function. If it is that we can not use ANY function then I am afraid we cannot use system time and other methods also, since they are also functions. – SureshS Mar 11 '13 at 03:12