Does anyone know if the Java's Random.nextInt() will ever repeat itself after sometime?
Concretely, is there such a number n such that the following two lists are equal?
List<Integer> a = new LinkedList<>();
List<Integer> b = new LinkedList<>();
for (int i = 0; i < n; ++i)
a.add(randObject.nextInt());
for (int i = n; i <= n * 2 ; ++i)
b.add(randObject.nextInt());
Is it guaranteed that every random object has a period?
(Note: Objects of different seeds don't have to have the same period)
Does anyone know if the Java's Random.nextInt() will ever repeat itself after sometime?
Yes it will. Since the generator has a finite amount of state, the generated sequence has a finite period.
Concretely, what is the number n such that the following two lists are equal?
That's not specified and depends on the Java implementation.
Is it guaranteed that there will always be such n for each Random object, regardless of what its seed is?
The period is finite. However, it's not necessarily the case that it's the same for every seed.
If you are really really really lucky enough, yes. Otherwise no.
But from the javadoc
The general contract of nextInt is that one int value is pseudorandomly generated and returned. All 2^32 possible int values are produced with (approximately) equal probability.
Related
How do I safely generate a random integer value in a specific range?
I know many people have asked this before, this post for example, but the method doesn't seem to be safe. Let me explain:
The 'Math' library has Math.random() which generates a random value in the range [0, 1). Using that, one can construct an algorithm like
int randomInteger = Math.floor(Math.random() * (Integer.MAX_VALUE - Integer.MIN_VALUE + 1) + Integer.MIN_VALUE)
to generate a random number between Integer.MAX_VALUE and Integer.MIN_VALUE. However, Integer.MAX_VALUE - Integer.MIN_VALUE will overflow.
The goal is not to merely generate random numbers but to generate them evenly, meaning 1 has the same probability to appear as Integer.MAX_VALUE. I know there are work-arounds to this, such as casting large values to long but then the problem again is how to generate a long integer value from Long.MIN_VALUE to Long.MAX_VALUE.
I'm also not sure about other pre-written algorithms as they can overflow too and cause the probability distribution to change. So my question is whether there is a mathematical equation that uses only integers (no casting to long anywhere) and Math.random() to generate random numbers from Integer.MIN_VALUE to Integer.MAX_VALUE. Or if anyone know any random generators that don't get overflow internally?
The 'Math' library have Math.random() which generates a random value in [0, 1) range.
So don't use Math.random() - use this:
Random r = new Random();
int i = r.nextInt();
The docs for nextInt say:
nextInt() - Returns the next pseudorandom, uniformly distributed int value from this random number generator's sequence. All 2^32 possible int values are produced with (approximately) equal probability.
It appears I misread the question slightly, and you need long not int - luckily the contract is the same.
long l = r.nextLong()
This will quite literally take two ints and jam them together to make a long.
Still better might be to use
java.security.SecureRandom which is a cryptographically strong random number generator (RNG).
Random x = new Random(1000); // code running and generate values 1000
int i = x.nextInt();
I just read from : Everything about java 8
that, java 8 adds Arrays.parallelSetAll()
int[] array = new int[8];
AtomicInteger i= new AtomicInteger();
Arrays.parallelSetAll(array, operand -> i.incrementAndGet());
[Edited] Is it O(1) or a constant time complexity on the same machine for same no.of elements in array ? What sort of performance improvement is indicated by the method name?
To start off, it can never be O(1), more clarification following:
I am using that n = array.length, which in your case is 8, however that does not matter as it could also be a very big number.
Now observe that normally you would do:
for (int i = 0; i < n; i++) {
array[i] = i.incrementAndGet();
}
This is with Java 8 much easier:
Arrays.setAll(array, v -> i.incrementAndGet());
Observe that they both take O(n) time.
Now take into account that you execute the code parallel, but there are no guarantees as to how it executes it, you do not know the number of parallellizations it does under the hood, if any at all for such a low number.
Therefore it still takes O(n) time, because you cannot prove that it will parallellize over n threads.
Edit, as an extra, I have observed that you seem to think that parallellizing an action means that any O(k) will converge to O(1), where k = n or k = n^2, etc.
This is not the case in practice as you can prove that you never have k processor cores available.
An intuitive argument is your own computer, if you are lucky it may have 8 cores, therefore the maximum time you could get under perfect parallellization conditions is O(n / 8).
I can already hear the people from the future laughing at that we only had 8 CPU cores...
It is O(N). Calling Arrays.parallelSetAll(...) involves assignments to set a total of array.length array elements. Even if those assignments are spread across P processors, the total number of assignments is linearly proportional to the length of the array. Take N as the length of the array, and math is obvious.
The thing to realize is that P ... the number of available processors ... is going to be a constant for any given execution of a program on a single computer. (Or if it is not a constant, there will be a constant upper bound.) And a computation whose sole purpose is to assign values to an array only makes sense when executed on a single computer.
I am writing a multi-threaded Java program that generates lot of random numbers.
Additional Details:
These numbers are used to create a list of random numbers from 0-99 without repetition and such that every number in the range 0-99 exists in the list (In other words, the list contains 100 unique elements in the range 0-99).
Generating Random Numbers [Things already tried!]
I have an ArrayList of numbers from 0-100. I generate a random number and use it as an index which is used to pop out an element from the ArrayList.
I have used Collections.shuffle().
Here is the code for approach 1:
ArrayList<Integer> arr = new ArrayList<Integer>();
for (int i = 0; i < N; i++){
arr.add(i, i);
}
for(int i=0; i<N; i++){
int indx = rand.nextInt(arr.size());
res.add(arr.get(indx));
arr.remove(indx);
}
For second approach, I replaced the second for loop with Collections.shuffle(arr).
As generating list of random numbers is the most expensive part of my algorithm, I want to optimize it. This brings me to the questions:
What is the fastest way to generate random numbers?
What is the fastest way to generate the list of random numbers as described above?
PS:
I found Collections.shuffle() to be slower than the first approach
Someone suggested me using rngd to generate random numbers from hardware in Unix. Has anyone tried this before? How do you do that?
I think the problem with Collections.shuffle() is that is uses default Random instance which is a thread-safe singleton. You say that your program is multi-threaded, so I can imagine synchronization in Random being a bottle-neck.
If you are happily running on Java 7, simply use ThreadLocalRandom. Look carefully, there is a version of shuffle() taking Random instance explicitly:
Collections.shuffle(arr, threadLocalRandom);
where threadLocalRandom is created only once.
On Java 6 you can simply create a single instance of Random once per thread. Note that you shouldn't create a new instance of Random per run, unless you can provide random seed every time.
Part of the problem might be the overhead of the Integer boxing and unboxing. You might find it helpful to reimplement the Fisher-Yates shuffle directly on an int[].
My approach woul be to generate the numbers with the Math.random() method as in the example here and initialize the list via a static init block like this:
private static List<int> list = new ArrayList<int>();
static {
for(int i = 0; i < 100; i++) {
// randomize number
list.add(number);
}
}
Hope this helped, have Fun!
To shuffle an array a of n elements (indices 0..n-1):
for i from n − 1 downto 1 do
j ← random integer with 0 ≤ j ≤ i
exchange a[j] and a[i]
Check Fischer and Yattes algorithm.
For example if java produces the pseudorandom sequence: 9 3 2 5 6
by using 23 as a seed, how can I do the inverse? i.e. getting 23 out of the sequence 9 3 2 5 6.
Or how do I assign a seed for a certain sequence?
It is easy to do if there is a database - just assign a random key for the sequence
INSERT INTO SEQUENCE_TABLE VALUES (RANDOM_KEY, SEQUENCE)
However if I'm not permitted to use a database, Is there a formula to do such a thing?
Yes, it's absolutely easy to reverse engineer the number stream of a poorly designed pseudo random number generator, such as the Linear Congruential PRNG implementation in the Java programming language (java.util.Random).
In fact, with as few as TWO values from that particular generator, and the information on the order in which the values emerged, the entire stream can be predicted.
Random random = new Random();
long v1 = random.nextInt();
long v2 = random.nextInt();
for (int i = 0; i < 65536; i++) {
long seed = v1 * 65536 + i;
if (((seed * multiplier + addend) & mask) >>> 16) == v2) {
System.out.println("Seed found: " + seed);
break;
}
}
This is precisely why it's critical to use cryptographically secure random number generators that have been vetted by the community at large for implementations that require security.
There is much more information on reverse engineering PRNGs, including java.util.Random here. ...
The point of random number generators is that this is impossible. SecureRandom is designed to be especially cryptographically strong, but generally speaking, if you're writing a random number generator and this is possible or easy, you're doing it wrong.
That said, it's likely that it's not impossible with Java's built in Random class. (SecureRandom is another story, though.) But it will require staggering amounts of math.
To be more specific: if a polynomial-time algorithm existed to do what you want, for some particular pseudorandom number generator, then it would by definition fail the "next-bit test" described in the linked Wikipedia article, since you could predict the next elements that would be generated.
It is certainly possible to recover the seed used by java.util.Random. This post describes the math behind Random's linear congruential formula, and here is a function to discover the current seed from the last two integers returned from nextInt().
public static long getCurrentSeed(int i1, int i2) {
final long multiplier = 0x5DEECE66DL;
final long inv_mult = 0xDFE05BCB1365L;
final long increment = 0xBL;
final long mask = ((1L << 48) - 1);
long suffix = 0L;
long lastSeed;
long currSeed;
int lastInt;
for (long i=0; i < (1<<16); i++) {
suffix = i;
currSeed = ((long)i2 << 16) | suffix;
lastSeed = ((currSeed - increment) * inv_mult) & mask;
lastInt = (int)(lastSeed >>> 16);
if (lastInt == i1) {
/* We've found the current seed, need to roll back 2 seeds */
currSeed = lastSeed;
lastSeed = ((currSeed - increment) * inv_mult) & mask;
return lastSeed ^ multiplier;
}
}
/* Error, current seed not found */
System.err.println("current seed not found");
return 0;
}
This function returns a value that can be used with rand.setSeed() to generate a pseudorandom sequence of numbers starting with i1 and i2.
If you're OK with using a String as your seed, you can use this:
String seed = "9 3 2 5 6";
Then your generator would look like:
String[] numbers = seed.split(" ");
If you truly want to reverse engineer the "random" number generator in java, that's going to be quite difficult (I think).
It would be better to do it the other way around if you can: Start with a seed, produce the sequence, then work out from there.
You want to take arbitrary sequences of numbers, then determine a short (fixed length?) key which will allow you to regenerate that sequence of numbers, without storing the original? Unfortunately, what you want is technically impossible. Here's why:
This is a particular case of compression. You have a long sequence of data, which you want to be able to recreate losslessly from a smaller piece of information. If what you are requesting were possible, then I would be able to compress the whole of stack overflow into a single integer (since the entire website could be serialized into a sequence of numbers, albeit a very long one!)
Unfortunately, mathematics doesn't work that way. Any given sequence has a particular measure of entropy - the average amount of complexity in that sequence. In order to reproduce that sequence losslessly, you must be able to encode at least enough information to represent its entropy.
For certain sequences, there may in fact be a seed that is capable of generating a long, specific sequence, but that is only because there is a hard-coded mathematical function which takes that seed and produces a particular sequence of numbers. However, to take an arbitrary sequence of values and produce such a seed, you would need both a seed, and a function capable of producing that sequence from that seed. In order to encode both of these things, you'd find that you've got a lot more data than you'd expect!
You are given a list of n numbers L=<a_1, a_2,...a_n>. Each of them is
either 0 or of the form +/- 2k, 0 <= k <= 30. Describe and implement an
algorithm that returns the largest product of a CONTINUOUS SUBLIST
p=a_i*a_i+1*...*a_j, 1 <= i <= j <= n.
For example, for the input <8 0 -4 -2 0 1> it should return 8 (either 8
or (-4)*(-2)).
You can use any standard programming language and can assume that
the list is given in any standard data structure, e.g. int[],
vector<int>, List<Integer>, etc.
What is the computational complexity of your algorithm?
In my first answer I addressed the OP's problem in "multiplying two big big numbers". As it turns out, this wish is only a small part of a much bigger problem which I'm going to address now:
"I still haven't arrived at the final skeleton of my algorithm I wonder if you could help me with this."
(See the question for the problem description)
All I'm going to do is explain the approach Amnon proposed in little more detail, so all the credit should go to him.
You have to find the largest product of a continuous sublist from a list of integers which are powers of 2. The idea is to:
Compute the product of every continuous sublist.
Return the biggest of all these products.
You can represent a sublist by its start and end index. For start=0 there are n-1 possible values for end, namely 0..n-1. This generates all sublists that start at index 0. In the next iteration, You increment start by 1 and repeat the process (this time, there are n-2 possible values for end). This way You generate all possible sublists.
Now, for each of these sublists, You have to compute the product of its elements - that is come up with a method computeProduct(List wholeList, int startIndex, int endIndex). You can either use the built in BigInteger class (which should be able to handle the input provided by Your assignment) to save You from further trouble or try to implement a more efficient way of multiplication as described by others. (I would start with the simpler approach since it's easier to see if Your algorithm works correctly and first then try to optimize it.)
Now that You're able to iterate over all sublists and compute the product of their elements, determining the sublist with the maximum product should be the easiest part.
If it's still to hard for You to make the connections between two steps, let us know - but please also provide us with a draft of Your code as You work on the problem so that we don't end up incrementally constructing the solution and You copy&pasting it.
edit: Algorithm skeleton
public BigInteger listingSublist(BigInteger[] biArray)
{
int start = 0;
int end = biArray.length-1;
BigInteger maximum;
for (int i = start; i <= end; i++)
{
for (int j = i; j <= end; j++)
{
//insert logic to determine the maximum product.
computeProduct(biArray, i, j);
}
}
return maximum;
}
public BigInteger computeProduct(BigInteger[] wholeList, int startIndex,
int endIndex)
{
//insert logic here to return
//wholeList[startIndex].multiply(wholeList[startIndex+1]).mul...(
// wholeList[endIndex]);
}
Since k <= 30, any integer i = 2k will fit into a Java int. However the product of such two integers might not necessarily fit into a Java int since 2k * 2k = 22*k <= 260 which fill into a Java long. This should answer Your question regarding the "(multiplication of) two numbers...".
In case that You might want to multiply more than two numbers, which is implied by Your assignment saying "...largest product of a CONTINUOUS SUBLIST..." (a sublist's length could be > 2), have a look at Java's BigInteger class.
Actually, the most efficient way of multiplication is doing addition instead. In this special case all you have is numbers that are powers of two, and you can get the product of a sublist by simply adding the expontents together (and counting the negative numbers in your product, and making it a negative number in case of odd negatives).
Of course, to store the result you may need the BigInteger, if you run out of bits. Or depending on how the output should look like, just say (+/-)2^N, where N is the sum of the exponents.
Parsing the input could be a matter of switch-case, since you only have 30 numbers to take care of. Plus the negatives.
That's the boring part. The interesting part is how you get the sublist that produces the largest number. You can take the dumb approach, by checking every single variation, but that would be an O(N^2) algorithm in the worst case (IIRC). Which is really not very good for longer inputs.
What can you do? I'd probably start from the largest non-negative number in the list as a sublist, and grow the sublist to get as many non-negative numbers in each direction as I can. Then, having all the positives in reach, proceed with pairs of negatives on both sides, eg. only grow if you can grow on both sides of the list. If you cannot grow in both directions, try one direction with two (four, six, etc. so even) consecutive negative numbers. If you cannot grow even in this way, stop.
Well, I don't know if this alogrithm even works, but if it (or something similar) does, its an O(N) algorithm, which means great performance. Lets try it out! :-)
Hmmm.. since they're all powers of 2, you can just add the exponent instead of multiplying the numbers (equivalent to taking the logarithm of the product). For example, 2^3 * 2^7 is 2^(7+3)=2^10.
I'll leave handling the sign as an exercise to the reader.
Regarding the sublist problem, there are less than n^2 pairs of (begin,end) indices. You can check them all, or try a dynamic programming solution.
EDIT: I adjusted the algorithm outline to match the actual pseudo code and put the complexity analysis directly into the answer:
Outline of algorithm
Go seqentially over the sequence and store value and first/last index of the product (positive) since the last 0. Do the same for another product (negative) which only consists of the numbers since the first sign change of the sequence. If you hit a negative sequence element swap the two products (positive and negative) along with the associagted starting indices. Whenever the positive product hits a new maximum store it and the associated start and end indices. After going over the whole sequence the result is stored in the maximum variables.
To avoid overflow calculate in binary logarithms and an additional sign.
Pseudo code
maxProduct = 0
maxProductStartIndex = -1
maxProductEndIndex = -1
sequence.push_front( 0 ) // reuses variable intitialization of the case n == 0
for every index of sequence
n = sequence[index]
if n == 0
posProduct = 0
negProduct = 0
posProductStartIndex = index+1
negProductStartIndex = -1
else
if n < 0
swap( posProduct, negProduct )
swap( posProductStartIndex, negProductStartIndex )
if -1 == posProductStartIndex // start second sequence on sign change
posProductStartIndex = index
end if
n = -n;
end if
logN = log2(n) // as indicated all arithmetic is done on the logarithms
posProduct += logN
if -1 < negProductStartIndex // start the second product as soon as the sign changes first
negProduct += logN
end if
if maxProduct < posProduct // update current best solution
maxProduct = posProduct
maxProductStartIndex = posProductStartIndex
maxProductEndIndex = index
end if
end if
end for
// output solution
print "The maximum product is " 2^maxProduct "."
print "It is reached by multiplying the numbers from sequence index "
print maxProductStartIndex " to sequence index " maxProductEndIndex
Complexity
The algorithm uses a single loop over the sequence so its O(n) times the complexity of the loop body. The most complicated operation of the body is log2. Ergo its O(n) times the complexity of log2. The log2 of a number of bounded size is O(1) so the resulting complexity is O(n) aka linear.
I'd like to combine Amnon's observation about multiplying powers of 2 with one of mine concerning sublists.
Lists are terminated hard by 0's. We can break the problem down into finding the biggest product in each sub-list, and then the maximum of that. (Others have mentioned this).
This is my 3rd revision of this writeup. But 3's the charm...
Approach
Given a list of non-0 numbers, (this is what took a lot of thinking) there are 3 sub-cases:
The list contains an even number of negative numbers (possibly 0). This is the trivial case, the optimum result is the product of all numbers, guaranteed to be positive.
The list contains an odd number of negative numbers, so the product of all numbers would be negative. To change the sign, it becomes necessary to sacrifice a subsequence containing a negative number. Two sub-cases:
a. sacrifice numbers from the left up to and including the leftmost negative; or
b. sacrifice numbers from the right up to and including the rightmost negative.
In either case, return the product of the remaining numbers. Having sacrificed exactly one negative number, the result is certain to be positive. Pick the winner of (a) and (b).
Implementation
The input needs to be split into subsequences delimited by 0. The list can be processed in place if a driver method is built to loop through it and pick out the beginnings and ends of non-0 sequences.
Doing the math in longs would only double the possible range. Converting to log2 makes arithmetic with large products easier. It prevents program failure on large sequences of large numbers. It would alternatively be possible to do all math in Bignums, but that would probably perform poorly.
Finally, the end result, still a log2 number, needs to be converted into printable form. Bignum comes in handy there. There's new BigInteger("2").pow(log); which will raise 2 to the power of log.
Complexity
This algorithm works sequentially through the sub-lists, only processing each one once. Within each sub-list, there's the annoying work of converting the input to log2 and the result back, but the effort is linear in the size of the list. In the worst case, the sum of much of the list is computed twice, but that's also linear complexity.
See this code. Here I implement exact factorial of a huge large number. I am just using integer array to make big numbers. Download the code from Planet Source Code.