4

I have made a very basic linear congruential generator (or at least I think I have) however it returns some crazy values including negative numbers. I cant for the life of me figure out why, any help very welcome. My code is below:

public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    long a = 252149039;
    int c = 11;
    long m =(long) Math.pow(2, 48);
    long seed = System.currentTimeMillis();
    System.out.println("How many Random numbers would you like to get?");
    int number = scanner.nextInt();
    for (int i = 0; i <= number;i++) {
        seed = ((a*seed)+c) % m;
        System.out.println(seed);
    }
    scanner.close();
}
R Hamilton
  • 263
  • 2
  • 14

2 Answers2

1

You're getting overflow errors. A java int long can only hold values up to 2^63-1, anything bigger than that wraps around. The mechanics of how this work deal with two's compliment integer representation, and the shortest fix would be to add

seed = seed >= 0 ? seed : seed + m

just before you print seed.

E.D.
  • 639
  • 6
  • 14
1

Because System.currentTimeMillis() returns the current time in milliseconds.
So, it may return big numbers such as 1508797287829.

Multiplying a number such as 1508797287829 by 252149039 (=380441786171888746331) :

... 
long a = 252149039;
long seed = System.currentTimeMillis();
...
seed = ((a*seed)+c) % m;

produces an overflow for the long seed variable as Long.MAX_VALUE is defined as 2^63 - 1 (=9223372036854775807).


To represent an arbitrary-precision integer, you could use BigInteger.
Note that the class is immutable.

You could declare seed as a BigInteger.

BigInteger seed = BigInteger.valueOf(System.currentTimeMillis());

And use it in this way :

seed = seed.multiply(BigInteger.valueOf(a))
           .add(BigInteger.valueOf(c))
           .mod(BigInteger.valueOf(m));
davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • can you show me how to correct this? I guess I can use bigInteger but im not sure how to do that. – R Hamilton Oct 23 '17 at 22:29
  • It is a way indeed. I updated with an example. Note that you have `mod()` and `remainder()` to compute the modulo. In your use case where you cannot have negative numbers, they should have the same behavior. – davidxxx Oct 23 '17 at 22:43