i am trying to create unique random identifier strategy. I do not want to store or query all ids that were already used, I'd like to use as a source of uniquesness a sequence generating numbers 0 -> Integer.MAX_VALUE. The thing I am thing that I am missing is a function that will project each number from the sequence to another in the same range.
Can you please point to some fast bijection function for this? (Prefferably in Java).
Thanks in advance
If you want to produce "unguessable" random numbers, you can take SecureRandom.nextLong() and append it with System.nanoTime(). The nanoTime part is easier to guess, but will not repeat after very short period of time. The nextLong part may repeat in future, but it's very hard to guess.
Note that if you have any determenistic bijection function hardcoded in your application and somebody will be able to obtain and reverse it (get sources, decompile class files, etc.), then your IDs will be compromised: it would be quite easy to find next/previous numbers by given one.
Related
I have an ArrayList which I want to grab a random value from. To do this I thought of two simple methods:
Method 1: Uses Random to generate a random number between 0 and the size of the ArrayList and then use that number for arrayList.get(x)
Method 2: Use arrayList.shuffle() and then arrayList.get(0).
Is one method preferable to the other in terms of randomness, I know it is impossible for one to be truly random but I want the result to be as random as possible.
EDIT: I only need one value from that ArrayList
It depends on the context.
Benefits of shuffling:
Once a shuffle, then just sequential grabbing
No repeated values
Benefits of randomizing:
Great for a small amount of values
Can repeat values
To answer your direct question: neither one of these is "more random" than the other. The results of the two methods are statistically indistinguishable. After all, the first step in shuffling an array is (basically) picking a number between 0 and N-1 (where N is the length of the array) and moving that element into the first position.
That being said, there are valid reasons to pick one or the other, depending on your specific needs. Jeroen's answer summarizes those well.
I would say the random number option is the best (Method 1).
Shuffling the objects takes up extra resources, because it has to move all of the objects around in the ArrayList, where generating a random number gives you the same effect without needing to use CPU time to cycle through array elements!
Also, be sure to generate a number between 0 and the size MINUS ONE. :)
If you just want one random selection, use Method 1. If you want to get a sequence of random selections with no duplicates, use Method 2.
Randomness depends on two factors, the algorithm (a.k.a the "generator") and the seed.
What generators does each method use?
The second overload of Collections.Shuffle() actually accepts a seeded Random. If you choose the default overload, it uses a Random anyway, as specified in the Javadoc. You're using a Random no matter what.
Are the generators seeded differently?
Another look at Random in the Javadoc shows that it is seeded by with some time value unless you specify a seed. Shuffle doesn't specify a time if you look at the implementation. You're using the default seed unless you specify one.
Because both use Random and both use the same default seed, they are equally random.
Which one has a higher time complexity?
Shuffling a list is O(n) (the Javadoc for Shuffle actually specifies linear time). The time complexity of Random.nextInt() is O(1). Obviously, the latter is faster in a case where only one value is needed.
When writing Java program, we use setSeed in the Random class. Why would we use this method?
Can't we just use Random without using setSeed? What is the main purpose of using setSeed?
One use of this is that it enables you to reproduce the results of your program in future.
As an example, I wanted to compute a random variable for each row in a database. I wanted the program to be reproducible, but I wanted randomness between rows. To do this, I set the random number seed to the primary key of each row. That way, when I ran the program again, I got the same results, but between rows, the random variable was pseudo random.
The seed is used to initialize the random number generator. A seed is used to set the starting point for generating a series of random numbers. The seed sets the generator to a random starting point. A unique seed returns a unique random number sequence.
This might be of help .
A pseudorandom number generator (PRNG), also known as a deterministic random bit generator DRBG, is an algorithm for generating a sequence of numbers that approximates the properties of random numbers. The sequence is not truly random in that it is completely determined by a relatively small set of initial values, called the PRNG's state, which includes a truly random seed.
I can see two reasons for doing this:
You can create a reproducible random stream. For a given seed, the same results will be returned from consecutive calls to (the same) nextX methods.
If two instances of Random are created with the same seed, and the same sequence of method calls is made for each, they will generate and return identical sequences of numbers
You feel, for some reason, that your seed is of a higher quality than the default source (which I'm guessing is derived from the current time on your PC).
A specific seed will always give the same sequence of "pseudo-random" numbers. So there are only 2^48 different sequences in Random because setSeed only uses 48-bits of the seed parameter! Besides setSeed, one may also use a constructor with a seed (e.g. new Random(seed)).
When setSeed(seed) or new Random(seed) are not used, the Random() constructor sets the seed of the random number generator to a value very likely to be distinct from any other invocation of this constructor.
Java reference for the above information: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Random.html
In the ordinary case, don't use a seed. Just use the empty constructor Random() and don't call setSeed. This way you'll likely get different pseudo-random numbers each time the class is constructed and invoked.
For data dependent debugging, where you want to repeat the same pseudo-random numbers, use a specific seed. In this case, use Random(seed) or setSeed(seed).
For non-security critical uses, there's no need to worry whether the specific seed/sequence might be recognized and subsequent numbers predicted, because of the large range of seeds. However, "Instances of java.util.Random are not cryptographically secure. Consider instead using SecureRandom to get a cryptographically secure pseudo-random number generator for use by security-sensitive applications." source
Several others have mentioned reproducibility. Reproducibility is at the heart of debugging, you need to be able to reproduce the circumstances in which the bug occurred.
Another important use of reproducibility is that you can play some statistical games to reduce the variability of some estimates. See Wikipedia's Variance Reduction article for more details, but the intuition is as follows. Suppose you're considering two different layouts for a bank or a grocery store. You can't build them both and see which works better, so you use simulation. You know from queueing theory that the size of lines and delays customers experience are partly due to the layout, but also partly due to the variation in arrival times, demand loads, etc, so you use randomness in your two models. If you run the models completely independently, and find that the lines are bigger in layout 1 than in layout 2, it might be because of the layout or it might be because layout 1 just happened to get more customers or a more demanding mix of transactions due to the luck of the draw. However, if both systems use the exact same set of customers arriving at the same times and having the same transaction demands, it's a "fairer" comparison. The differences you observe are more likely to be because of the layout. You can accomplish this by reproducing the randomness in both systems - use the same seeds, and synchronize so that the same random numbers are used for the same purpose in both systems.
I used int as PK in Java application, now it has reached the max int value (2 billions), even in DB it can store the number more than it. but java int is only able to hold around 2 billions.
I am unable to change int to long to align to DB. because it's huge effort.
except this, anybody have any approach?
The maximum value for an Integer in Java is 2,147,483,647. If you need a bigger number, you'll have to change to a long. You could also use the negative range of the Integer, but if you've already hit the maximum, the likelihood is that you'll run out of room pretty soon.
However, if you don't have 2 billion elements in the DB, you could reuse the unused primary keys. This would probably be inefficient, because you'd have to search for unused keys.
I'd suggest just going through the effort of changing the code. Putting in the effort now will pay off in the long run.
I am unable to change int to long to align to DB. because it's huge effort.
You have no alternatives in the long term. Start coding.
Actually, if you are methodical about it, you will probably find that it is not a huge effort at all. Java IDEs are good for helping you with this sort of change.
#jjnguy suggested you let the keys wrap around to negative. That would give you 2 billion or so extra keys, but:
you will probably use the second 2 billion faster quicker than the first 2 billion, and
it is possible that your application (or the database) depends on keys always increasing.
So I would avoid that, unless roll-over was imminent.
I'm assuming you haven't used negative values for the IDs. If that's the case, you can let the value overflow to negative values. This will give you some time to refactor your code to use a long to store your data.
you need just to replace int with uint, long and etc. there is no other way
Everyone here suggests to change to long. This seems to me also the most straightforward approach. However, you ask for a different one.
You could also create another column, with long values, copy the value from the PK, and setting that henceforth as the PK. Although I would see this technically as more work, maybe for your situation it is better, and strictly it is an answer to your question of another approach.
(Maybe you have some sort of sharded situation with thousand shards which you canĀ“t possibly all in the same time swap over). Either way be very careful! Run tests!
Use BigInteger class in Java. You can get large and by large i mean really very large values. Please refer to this link: How to use BigInteger?
Does anybody know of a good way to generate a random String of specified length and characters in Java.
For example 'length' could be 5 and 'possibleChars' could be 'a,b,c,1,2,3,!'.
So
c!a1b is valid
BUT
cba16 is not.
I could try to write something from scratch but I feel like this must be a common use case for things like generating passwords, generating coupon codes, etc...
Any ideas?
You want something like this?
Random r=new Random();
char[] possibleChars="abc123!".toCharArray();
int length=5;
char[] newPassword=new char[length];
for (int i=0; i<length;i++)
newPassword[i]=possibleChars[r.nextInt(possibleChars.length)];
System.out.println(new String(newPassword));
The code to do this is pretty short. Have a char[] or String with N legal chars, and, length times, pick a random number R between 0 and N-1, use R to pick a character to append to your generated String.
I could try to write something from scratch but I feel like this must be a common use case for things like generating passwords, generating coupon codes, etc...
It is not that common, and the detailed requirements are different each time. Besides, the code is simple to the point of being trivial. (Modulo the concerns below ... which are really about the requirements rather than the solution.)
In short, it is quicker to write your own method than to go looking for an existing library method that does this.
When you use a scheme that involves random numbers, you need to be aware of the possibility that you will get collisions; i.e. that the method will generate the same random string on more than one occasion. You can mitigate this by using a longer string, but that only works to a certain point ... depending on your random number generator. (Typical random number generators are actually pseudo-random number generators, and produce a sequence of numbers that eventually cycle around. And even with a perfect random number generator there is a finite probability of repeats over a short sequence.)
In fact, this is another reason why a "one size fits all" solution to your problem is not a good idea.
If this is for real security, as opposed to homework or a programming exercise, then use SecureRandom, not Random.
Read the Diceware website for a lot of very good ideas on the random generation of passwords and other things.
there is some ways to generate random Numbers in java
one of them is this:
Random rand=new Random();
int randomInteger=rand.nextInt();
now my question is this: can we predict next random Number?
edited after 4 answers:
my real problem is this:
I'm working on a Snake Game( nibbles in Linux) and I'm programing the snake to move, now I want to know if it's possible to Predict the next place that the apple will appear.
is it possible?
You can not only predict it, but know it absolutely, if you know exactly what System.currentTimeMillis would return when you called new Random(). That's because new Random() is a shortcut for new Random(System.currentTimeMillis()), which sets the seed of a pseudo-random generator. (Well, that's what it did when I last looked at the source; the docs don't actually say it has to use that.) if you know the seed that new Random() used. Pseudo-random generators are deterministic, if you know the seed, you know the sequence. Update: Looking at the Java 6 source [I don't have Java 7 source handy], the default seed is a combination of a seed number that gets incremented on use, plus System.nanoTime. So you'd need to know both of those. Raises the bar.
If you don't know the exact value of System.currentTimeMillis() as of when new Random() occurs the seed used by new Random(), then it's very difficult indeed to predict what the next value will be. That's the point of pseudo-random generators. I won't say it's impossible. Just really, really hard to do with any degree of confidence.
Update after question edit: It's possible, but very, very hard, and in terms of doing so in a way that would allow a player to improve their score in the game, I'd say you can ignore it.
The "random" numbers generated by the Random class are generated algorithmically, and as such are really pseudo-random numbers. So yes, in theory, you can predict the next number. Knowing one number that Random has produced, though, or even a series of numbers, isn't enough information to predict the next number; you would also need to know the seed that the Random object is using, and you would need to follow its pseudo-random number generation algorithm.
If you would like a repeatable set of "random" numbers, you can specify your own seed when creating an instance of Random, e.g.
Random rand = new Random(1234); // Replace 1234 with any value you'd like
Every time you instantiate Random with the same seed, you'll get the same series of numbers. So, for example, you could write a small command-line program that instantiates Random with some seed and prints a list of the numbers it returns, and then instantiate Random with the same seed in your code. Then you would know which numbers your code will receive and in what order. That's very handy for debugging.
There could be NO really random numbers on deterministic devices like computer. But.
If you want a cryptographically secure random number, use SecureRandom: http://docs.oracle.com/javase/6/docs/api/java/security/SecureRandom.html
Random uses a deterministic algorithm:
If two instances of Random are created with the same seed, and the same sequence of method calls is made for each, they will generate and return identical sequences of numbers.
http://docs.oracle.com/javase/6/docs/api/java/util/Random.html#Random
Essentially, if you know the seed of the random number generator, you can predict the entire sequence with certainty. If you don't, no matter how many numbers you generate, there's no way to accurately predict the next one.
Note that if you're relying on the numbers being unpredictable for security, you should be using java.secure.SecureRandom rather than java.util.Random.
As others answer this question, it is possible to predict randomness of java.util.Random if you know the starting seed.
If you are working on a linux like system, take a look at these special files /dev/random and dev/urandom. Reads from these files are said to return "better" random numbers, the randomness depends on keyboard activity, mouse movement and some other exotic factors.
See this Wikipedia page for details. This page also says equivalent APIs exist in Windows.