Current location - Education and Training Encyclopedia - Graduation thesis - Uniq development paper
Uniq development paper
Hello, I am crooked.

I recently saw a piece of code on stackoverflow.

It just looked silly at first sight, but when I understood it, I knelt down directly!

Let me show you what this problem is on stackoverflow first, and then lead out this code:

The problem is particularly simple, just one sentence:

Who can explain to me: Why does this code print out hello world using random strings?

The code is also very simple. Let me show it to you:

You can also paste the above code directly into your running environment and run it to see if it is also output as hello world:

Let me ask you one question: Even if I gave you all the codes, were you at a loss when I first saw hello world?

Gao Zan replied.

Gao Zan's answer is also very simple, just two sentences.

Let me translate it for you. This guy said:

When we call Random's constructor, we get a "seed" parameter. For example: -229985452 or-147909649 in this example.

Then Random will generate random numbers starting from the specified seed value.

And each random object constructed with the same seed will generate numbers according to the same pattern.

I didn't see it clearly, did I?

It doesn't matter, I'll give you a piece of code, and you can suddenly realize what the above paragraph says:

This code runs on my machine and the result is as follows:

You run with it, and the result of your running must be like this.

Why is this?

The answer is written on Javadoc:

In the above code, two -229985452 are the same seed, and three calls to nextInt () are the same call sequence.

Therefore, they generate and return seemingly random identical numbers.

Our normal usage in the program should be like this:

When new Random (), no value is specified.

We all know that Random is a pseudo-random algorithm, and it is a more pseudo-random algorithm to specify seed parameters during construction.

Because if I can guess your seed, or if your seed is leaked, then theoretically I can guess your random number generation sequence.

I have demonstrated this in the previous code.

I explained the key points of "seed" a little earlier, and then I went back to the question of tasting, so I can probably see some clues.

Mainly look at the code in this loop.

First of all, nextInt(27) defines that the number k currently returned must be a number between [0,27].

If 0 is returned, the loop ends; Otherwise, the loop ends. Then do a type conversion.

Then there is a cast of type char.

When you see a number change to a char type, you should consider the ascii code in a conditional way:

From the ascii code table, we can see that "96" is the symbol here:

Therefore, the range of the following code is [96+ 1, 96+26]:

That is [97, 122], which is the a-z corresponding to ascii code.

So, I'll take you to disassemble the demo code above.

The first is the first five returns of NewRandom (-229985452). Nextint (27) is as follows:

The first five returns of NewRandom (-147909649). Nextint (27) is as follows:

So, when you look at the ascii code table, you can see its corresponding letters:

Now, as for why this inscrutable code outputs "hello world", is it clear to me that it is like a mirror?

Yes, it's just a scam.

Then there is a comment below this question, which shows me another way to open it:

You can specify to print hello world, so theoretically I can also specify to type other words.

For example, this brother typed a phrase: the quick brown fox jumped over a lazy dog.

If translated literally, it means "a quick brown fox crosses a lazy dog", which seems to be nonsense.

However, you should know that my English level is relatively high, and it is certainly not easy to see this sentence at first sight here.

So I checked:

Sure enough, there is a story, which belongs to the trick in the trick.

After reading this brother's fast brown fox example, I have a new idea.

Since it can type all the letters, can I type the specific phrase I want?

I'm fine, thank you, and you.

In the answer to this question, the "good man" has written the code to find the function of seed corresponding to the specified word.

I'll post it directly, or you can use it directly:

So I'm looking for the sentence mentioned before, which is very simple:

And when I was running, I obviously felt that I spent a lot of time searching for the word "thank you".

Why?

Let me tell you a story. There is only one sentence that you must have heard:

Our generateSeed method here is equivalent to this monkey. The word gratitude is Shakespeare.

In the generateSeed method, "thank you" can always be arranged through the continuous arrangement and combination of 26 letters, but it can only be arranged for a short time.

The longer the word, the longer it takes.

For example, I will have a congratulations, such a long sentence, from 00: 05 to now 23 hours did not run out:

But in theory, as long as there is enough time, this seed will be found.

At this point, you should fully understand why the code mentioned above will be printed in hello world with random strings.

You think I want to show you the source code?

No, I mainly take you to eat melons.

First, look at the random parameterless constructor:

Boy, it turned out to be a "parameterless" shell. In fact, I made a seed myself and then called the parameter constructor.

It's just that the variable "System.nanoTime ()" is added at the time of construction, which makes the seed look a bit random.

Wait, isn't there another "seedUniquifier" method ahead?

This method is like this:

Boy, when I first saw it, my head was big. There are two "magic numbers":

You don't understand this thing either?

Never make up your mind, Starkflow.

A search will find this place:

In this question, he said that he was also puzzled by these two figures. He searched the Internet for a circle and found little relevant information. But I found a paper, which mentioned a very close "magic number":

The figures mentioned in the article are as follows:

Do you see it?

The number in this Java source code is missing a "1". What happened? You can't make mistakes when copying, can you?

The following are highly praised answers:

"It really looks like a mistake."

Very interesting. If you want to say that this is the code that my brother copied when writing Java source code, I will be excited.

It's really unexpected to go to the Java Bug page right away and search with that string of numbers:

In the description of this bug, he drew my attention to this place in the source code:

It turns out that the label of this place represents a paper, so the source of this number must be hidden in this paper.

Wait, why do I think the name of this paper is a little familiar?

The link mentioned in the previous stackoverflow is a paper address:

See if the title of this paper is the same as the annotation in Java:

That must be the same thing, just a lowercase and a uppercase.

So, this is the real hammer. It's really the first time to write my brother's copy number in Java, and I lost a "1".

Moreover, I can even imagine that when that brother was writing this part of the source code, he posted the number "1178349727652981"and found: Hey, why are there two1in front? It was copied and deleted.

As for deleting this "1", what problems will it bring?

Anyway, there is a correlation problem here, saying that the randomness of calling new Random () concurrently is not big enough.

I didn't study this. You can go and have a look if you are interested. I only take you to eat melons.

So, based on this "melon", the official made a modification to this code:

I happen to have JDK 15 and JDK 8 versions of the code here. At first glance, it's really the difference between "1":

As for Random numbers, random is rarely used now.

Directly on ThreadLocalRandom, is it fragrant?

What, you refused?