Generate random characters with the Random class

Asked

Viewed 1,629 times

0

I was given the following code to help in the resolution of an exercise.

Random gerador = new Random();
gerador.setSeed(4);
System.out.println((char)(’a’ + (Math.abs(gerador.nextInt()) % 26)));

I created a class to test the code:

public class Random {

    private static final Random gerador = new Random();  

    public static void main (String[] args){

        gerador.setSeed(4);    
        System.out.println((char)('a' + Math.abs(gerador.nextInt() % 26)));

    }//fim do main

}//fim da classe

1 - The following error has been returned when I try to compile:

Random.java:15: error: cannot find symbol
    gerador.setSeed(4);
           ^
  symbol:   method setSeed(int)
  location: variable gerador of type Random
Random.java:17: error: cannot find symbol
    System.out.println((char)('a' + Math.abs(gerador.nextInt() % 26)));
                                                    ^
  symbol:   method nextInt()
  location: variable gerador of type Random
2 errors

2 - Besides the mistake, I don’t understand what makes the .setSeed

As for the part of the code:

(char)('a' + Math.abs(gerador.nextInt() % 26))

I understand that the Math.abs() will take the absolute value of the rest of the entire division of a random number divided by 26.

3- But why is this value being concatenated with: 'a'?

1 answer

2


The code is using the class java.util.Random, which is a native Java class for random number generation.

The problem is that you have created a class with the same name (Random), and then the compiler tries to find the methods setSeed and nextInt in its class. And since these methods do not exist, it gives the build error.

So the first thing to do is to change the name of your class to anything other than Random. And don’t forget to do the import class java.util.Random also:

import java.util.Random;

public class TestRandom { // mude o nome da classe para outro que não seja Random

    private static final Random gerador = new Random();

    public static void main(String[] args) {
        // agora tudo compila
        gerador.setSeed(4);
        System.out.println((char) ('a' + Math.abs(gerador.nextInt() % 26)));
    }
}

As for the method setSeed, well, it changes the Seed of the object Random. In summary, the numbers generated by this class are not purely random. In fact they are pseudo-random, because what happens internally are various calculations that generate numbers that seem like random.

And all these calculations start from an initial value, called Seed. If two objects Random are created with the same Seed, they will generate the same sequence. See documentation for more details.

That said, use setSeed and always pass the same value, as you did, will result in the same number being generated every time this code is executed.

If you want the result to be more random and not the same every run, you do not need to use setSeed. When you create a new object Random (with new Random()), it is already initialized with a Seed that, according to the documentation, is "very likely to be different from any other invocation of this constructor".


As to his last doubt, the number resulting from the expression Math.abs(...) is not being concatenated to char, and yes added.

This happens because a char - briefly - can also be treated as a number. Ex:

char c = 'a';
System.out.println((int) c); // 97

By doing the cast for int, is printed 97, which is the value of Codepoint corresponding to the character a (on this link the value of Codepoint is U+0061, since Unicode uses hexadecimal values - to better understand how codepoints of Unicode, I suggest reading of this article and of this question).

It is also possible to pass a numerical value directly by doing the cast for char, and the result is the character whose Codepoint has that numerical value. Ex:

char c = (char) 39321;
System.out.println(c); // 香

In this case, the char will have the character that corresponds to the Codepoint 39321 (in this case, the character - and see again on this link that the value is in hexadecimal: U+9999).

And as a char can be manipulated as number, we can also add a value to the same:

char c = 'a' + 1;
System.out.println((int) c); // 98
System.out.println(c); // b

This code prints out:

98
b

That is, by adding 1 to the character a, the result is the Codepoint corresponding to a (that we have seen that it is 97) added to the number 1, which is 98. So the char becomes the character corresponding to Codepoint 98, which is the letter b.


So what your code does is get a letter between a and z, since the result of % 26 always returns a number between 0 and 25 (when it is zero, the result will be itself a, and when it’s 25, it’ll be z). This is only possible because the codepoints these characters are sequential: the Codepoint of the letter b is exactly 1 above the a, the c is 1 above the b, etc.. See this link for more details.


Another option to do the same thing is pass a parameter to nextInt, indicating the maximum value that can be returned:

System.out.println((char) ('a' + gerador.nextInt(26)));

With nextInt(26), the result is an integer between zero and 25. This eliminates the need to use % 26 and Math.abs.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.