Class random

Основные математические функции

Java.lang.Math содержит набор базовых математических функций для получения абсолютного значения, наибольшего и наименьшего из двух значений, округления значений, случайных значений и т. д.

Math.abs()

Функция Math.abs() возвращает абсолютное положительное значение переданного ей параметра. Если значение параметра является отрицательным, знак «-» удаляется и возвращается положительное значение, соответствующее отрицательному значению без знака. Вот два примера:

int abs1 = Math.abs(10);  // abs1 = 10

int abs2 = Math.abs(-20); // abs2 = 20

Абсолютное значение 10 равно 10. Абсолютное значение -20 равно 20.

Метод Math.abs() представлен в 4 версиях:

Math.abs(int)
Math.abs(long)
Math.abs(float)
Math.abs(double)

Какой из этих методов вызывается, зависит от типа параметра, передаваемого методу Math.abs().

Math.ceil()

Функция округляет значение с плавающей запятой до ближайшего целого числа. Округленное значение возвращается как двойное. Вот пример:

double ceil = Math.ceil(7.343);  // ceil = 8.0

После выполнения этого Java-кода переменная ceil будет содержать значение 8.0.

Math.floor()

Функция Math.floor() округляет значение с плавающей запятой до ближайшего целочисленного значения. Округленное значение возвращается как двойное. Вот пример:

double floor = Math.floor(7.343);  // floor = 7.0

После выполнения ceil будет содержать значение 8.0.

Math.floorDiv()

Метод Math.floorDiv() делит одно целое число (int или long) на другое и округляет результат до ближайшего целочисленного значения. Если результат положительный, эффект такой же, как при использовании оператора «/» (деления), описанного ранее в этом тексте.

Однако, если результат отрицательный, результат не тот же. С помощью оператора «/» дроби просто усекаются. Для положительных чисел это соответствует округлению в меньшую сторону, для отрицательных — в большую. Метод floorDiv() округляет до ближайшего отрицательного целого числа, вместо того, которое будет происходить при усечении дроби.

Вот пример:

double result3 = Math.floorDiv(-100,9);
System.out.println("result3: " + result3);

double result4 = -100 / 9;
System.out.println("result4: " + result4);

Выходные данные:

result3: -12.0
result4: -11.0

Это показывает разницу между оператором «/» и Math.floorDiv().

Math.min()

Метод Math.min() возвращает наименьшее из двух значений, переданных ему в качестве параметра:

int min = Math.min(10, 20);

После выполнения этого кода переменная min будет содержать значение 10.

Math.max()

Метод Math.max() возвращает наибольшее из двух значений, переданных ему в качестве параметра:

int max = Math.max(10, 20);

После выполнения этого кода переменная max будет содержать значение 20.

Генерирование целочисленных псевдослучайных значений

Для генерирования целочисленных псевдослучайных значений используется представленное выше выражение, в котором
произведение «приводится» к целочисленному значению. Например, попробуем получить псевдослучайное значение в диапазоне

Обратите внимание, что закрывающаяся скобка квадратная, т.е. 20 входит в диапазон

В этом случае к разности
между максимальным и минимальным значениями следует добавить 1, т.е. определить диапазон целочисленных значений [5,21),
где 21 не попадает в желаемый диапазон :

// после подстановки значений
int i = (int)Math.random() * (20 - 5 + 1) + 5;
// получаем
int i = (int)Math.random() * 16 + 5;

Пример

Тем не менее, в разработке, мы встречаем ситуаций, где нам нужно использовать объекты вместо примитивных типов данных. Для того чтобы достичь этого Java предоставляет классы-оболочки.

Все классы-оболочки (Integer, Long, Byte, Double, Float, Short) являются подклассами абстрактного класса чисел в Java (class Number).

Объект класса-оболочки содержит или обертывает свой соответствующих примитивный тип данных. Конвертирование примитивных типов данных в объект называется упаковка, и об этом заботится компилятором. Поэтому при использовании класса-оболочки необходимо просто передать конструктору класса-оболочки значение примитивного типа данных.

Объект оболочки может быть преобразован обратно в примитивный тип данных, и этот процесс называется распаковка. Класс чисел является частью пакета java.lang.

Вот пример упаковки и распаковки:

Будет получен следующий результат:

Когда х присваивается целое значение, компилятор упаковывает целое число, потому что х это целочисленный объект. Позже распаковывает х так, чтобы он мог быть добавлен в виде целого числа.

Тригонометрические функции

Класс Java Math содержит набор тригонометрических функций. Эти функции могут вычислять значения, используемые в тригонометрии, такие как синус, косинус, тангенс и т. д.

Mathkpi

Константа Math.PI представляет собой двойное значение, значение которого очень близко к значению PI — математическому определению PI.

Math.sin()

Метод Math.sin() вычисляет значение синуса некоторого значения угла в радианах:

double sin = Math.sin(Math.PI);
System.out.println("sin = " + sin);

Math.cos()

Метод Math.cos() вычисляет значение косинуса некоторого значения угла в радианах:

double cos = Math.cos(Math.PI);
System.out.println("cos = " + cos);

Math.tan()

Метод Math.tan() вычисляет значение тангенса некоторого значения угла в радианах:

double tan = Math.tan(Math.PI);
System.out.println("tan = " + tan);

Math.asin()

Метод Math.asin() вычисляет значение синусоиды значения от 1 до -1:

double asin = Math.asin(1.0);
System.out.println("asin = " + asin);

Math.acos()

Метод Math.acos() вычисляет значение арккосинуса от 1 до -1:

double acos = Math.acos(1.0);
System.out.println("acos = " + acos);

Math.atan()

Метод Math.atan() вычисляет значение арктангенса для значения от 1 до -1:

double atan = Math.atan(1.0);
System.out.println("atan = " + atan);

Вот что говорит JavaDoc:

Если вам нужен этот метод, пожалуйста, прочитайте JavaDoc.

Math.sinh()

Метод Math.sinh() вычисляет значение гиперболического синуса значения между 1 и -1:

double sinh = Math.sinh(1.0);
System.out.println("sinh = " + sinh);

Math.cosh()

Метод Math.cosh() вычисляет значение гиперболического косинуса от 1 до -1:

double cosh = Math.cosh(1.0);
System.out.println("cosh = " + cosh);

Math.tanh()

Метод Math.tanh() вычисляет значение гиперболического тангенса значения от 1 до -1:

double tanh = Math.tanh(1.0);
System.out.println("tanh = " + tanh);

Math.toDegrees()

Метод Math.toDegrees() преобразует угол в радианах в градусы:

double degrees = Math.toDegrees(Math.PI);
System.out.println("degrees = " + degrees);

Math.toRadians()

Метод Math.toRadians() преобразует угол в градусах в радианы:

double radians = Math.toRadians(180);
System.out.println("radians = " + radians);

Method Summary

All MethodsInstance MethodsConcrete Methods

Modifier and Type Method Description
Returns an effectively unlimited stream of pseudorandom values, each between zero (inclusive) and one
(exclusive).
Returns an effectively unlimited stream of pseudorandom values, each conforming to the given origin (inclusive) and bound
(exclusive).
Returns a stream producing the given number of
pseudorandom values, each between zero
(inclusive) and one (exclusive).
Returns a stream producing the given number of
pseudorandom values, each conforming to the given origin
(inclusive) and bound (exclusive).
Returns an effectively unlimited stream of pseudorandom
values.
Returns an effectively unlimited stream of pseudorandom values, each conforming to the given origin (inclusive) and bound
(exclusive).
Returns a stream producing the given number of
pseudorandom values.
Returns a stream producing the given number
of pseudorandom values, each conforming to the given
origin (inclusive) and bound (exclusive).
Returns an effectively unlimited stream of pseudorandom
values.
Returns a stream producing the given number of
pseudorandom values.
Returns an effectively unlimited stream of pseudorandom values, each conforming to the given origin (inclusive) and bound
(exclusive).
Returns a stream producing the given number of
pseudorandom , each conforming to the given origin
(inclusive) and bound (exclusive).
Generates the next pseudorandom number.
Returns the next pseudorandom, uniformly distributed
value from this random number generator’s
sequence.
Generates random bytes and places them into a user-supplied
byte array.
Returns the next pseudorandom, uniformly distributed
value between and
from this random number generator’s sequence.
Returns the next pseudorandom, uniformly distributed
value between and from this random
number generator’s sequence.
Returns the next pseudorandom, Gaussian («normally») distributed
value with mean and standard
deviation from this random number generator’s sequence.
Returns the next pseudorandom, uniformly distributed
value from this random number generator’s sequence.
Returns a pseudorandom, uniformly distributed value
between 0 (inclusive) and the specified value (exclusive), drawn from
this random number generator’s sequence.
Returns the next pseudorandom, uniformly distributed
value from this random number generator’s sequence.
Sets the seed of this random number generator using a single
seed.

Методы класса чисел

Список методов всех подклассов класса чисел в Java:

Метод с описанием
1 xxxValue()
Преобразует значение целочисленного объекта в ххх тип данных и возвращает его.
2 compareTo()
Сравнивает целочисленный объект с аргументом.
3 equals()
Определяет, является ли целочисленный объект равным аргументу.
4 valueOf()
Возвращает целочисленный объект, держа указанное значение.
5 toString()
Возвращает строковый объект (String), представляющий указанное значение int или целочисленный объект.
6 parseInt()
Метод используется для получения примитивного типа данных определенной строки.
7 abs()
Возвращает абсолютное значение аргумента.
8 ceil()
Возвращает наименьшее (ближайшее к отрицательной бесконечности) double значение, которое больше или равно аргументу и равное математическому целому числу.
9 floor()
Возвращает наибольшее (ближайшее к положительной бесконечности) double значение, которое меньше или равно аргумента и равно математическому целому числу.
10 rint()
Возвращает double значение, которое ближе всего по значению аргумента и равно математическому целому числу.
11 round()
Возвращает ближайшее long или int к аргументу по правилам округления.
12 min()
Возвращает меньшее из двух аргументов.
13 max()
Возвращает большее из двух аргументов.
14 exp()
Возвращает число е Эйлера, возведенную в степень double значения.
15 log()
Возвращает натуральный логарифм (по основанию е) с double значением.
16 pow()
Возвращает значение первого аргумента, возведенное в степень второго аргумента.
17 sqrt()
Возвращает правильно округленный положительный квадратный корень из double значения.
18 sin()
Возвращает синус указанного double значения.
19 cos()
Возвращает косинус указанного double значения.
20 tan()
Возвращает тангенс указанного double значения.
21 asin()
Возвращает арксинус указанного double значения.
22 acos()
Возвращает арккосинус указанного double значения.
23 atan()
Возвращает арктангенс указанного double значения.
24 atan2()
Возвращает угол тета от преобразования прямоугольных координат (x, y) в полярных координатах (г, тета).
25 toDegrees()
Преобразует угол, измеренный в радианах в примерно эквивалентном угол, измеренный в градусах.
26 toRadians()
Преобразует угол, измеренный в градусах, в приблизительно эквивалентный угол, измеренный в радианах.
27 random()
Возвращает double значение с положительным знаком, больше чем или равно 0.0 и меньше чем 1.0 .
Поделитесь:

Using Third-Party APIs

As we have seen, Java provides us with a lot of classes and methods for generating random numbers. However, there are also third-party APIs for this purpose.

We’re going to take a look at some of them.

3.1. org.apache.commons.math3.random.RandomDataGenerator

There are a lot of generators in the commons mathematics library from the Apache Commons project. The easiest, and probably the most useful, is the RandomDataGenerator. It uses the Well19937c algorithm for the random generation. However, we can provide our algorithm implementation.

Let’s see how to use it. Firstly, we have to add dependency:

The latest version of commons-math3 can be found on Maven Central.

Then we can start working with it:

3.2. it.unimi.dsi.util.XoRoShiRo128PlusRandom

Certainly, this is one of the fastest random number generator implementations. It has been developed at the Information Sciences Department of the Milan University.

The library is also available at Maven Central repositories. So, let’s add the dependency:

This generator inherits from java.util.Random. However, if we take a look at the JavaDoc, we realize that there’s only one way of using it —  through the nextInt method. Above all, this method is only available with the zero- and one-parameter invocations. Any of the other invocations will directly use the java.util.Random methods.

For example, if we want to get a random number within a range, we would write:

Random Numbers Using the Math Class

Java provides the Math class in the java.util package to generate random numbers.

The Math class contains the static Math.random() method to generate random numbers of the double type.

The random() method returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0. When you call Math.random(), under the hood, a java.util.Random pseudorandom-number generator object is created and used.

You can use the Math.random() method with or without passing parameters. If you provide parameters, the method produces random numbers within the given parameters.

The code to use the Math.random() method:

The getRandomNumber() method uses the Math.random() method to return a positive double value that is greater than or equal to 0.0 and less than 1.0.

The output of running the code is:

Random Numbers Within a Given Range

For generating random numbers between a given a range, you need to specify the range. A standard expression for accomplishing this is:

Let us break this expression into steps:

  1. First, multiply the magnitude of the range of values you want to cover by the result that Math.random() produces.returns a value in the range ,max–min where max is excluded. For example, if you want 5,10], you need to cover 5 integer values so you can use Math.random()*5. This would return a value in the range ,5, where 5 is not included.
  2. Next, shift this range up to the range that you are targeting. You do this by adding the min value.

But this still does not include the maximum value.

To get the max value included, you need to add 1 to your range parameter (max — min). This will return a random double within the specified range.

There are different ways of implementing the above expression. Let us look at a couple of them.

Random Double Within a Given Range

By default, the Math.random() method returns a random number of the type double whenever it is called. The code to generate a random double value between a specified range is:

You can call the preceding method from the main method by passing the arguments like this.

The output is this.

Random Integer Within a Given Range

The code to generate a random integer value between a specified range is this.

The preceding getRandomIntegerBetweenRange() method produces a random integer between the given range. As Math.random() method generates random numbers of double type, you need to truncate the decimal part and cast it to int in order to get the integer random number. You can call this method from the main method by passing the arguments as follows:

The output is this.

Note: You can pass a range of negative values to generate a random negative number within the range.

Using Java API

The Java API provides us with several ways to achieve our purpose. Let’s see some of them.

2.1. java.lang.Math

The random method of the Math class will return a double value in a range from 0.0 (inclusive) to 1.0 (exclusive). Let’s see how we’d use it to get a random number in a given range defined by min and max:

2.2. java.util.Random

Before Java 1.7, the most popular way of generating random numbers was using nextInt. There were two ways of using this method, with and without parameters. The no-parameter invocation returns any of the int values with approximately equal probability. So, it’s very likely that we’ll get negative numbers:

If we use the netxInt invocation with the bound parameter, we’ll get numbers within a range:

This will give us a number between 0 (inclusive) and parameter (exclusive). So, the bound parameter must be greater than 0. Otherwise, we’ll get a java.lang.IllegalArgumentException.

Java 8 introduced the new ints methods that return a java.util.stream.IntStream. Let’s see how to use them.

The ints method without parameters returns an unlimited stream of int values:

We can also pass in a single parameter to limit the stream size:

And, of course, we can set the maximum and minimum for the generated range:

2.3. java.util.concurrent.ThreadLocalRandom

Java 1.7 release brought us a new and more efficient way of generating random numbers via the ThreadLocalRandom class. This one has three important differences from the Random class:

  • We don’t need to explicitly initiate a new instance of ThreadLocalRandom. This helps us to avoid mistakes of creating lots of useless instances and wasting garbage collector time
  • We can’t set the seed for ThreadLocalRandom, which can lead to a real problem. If we need to set the seed, then we should avoid this way of generating random numbers
  • Random class doesn’t perform well in multi-threaded environments

Now, let’s see how it works:

With Java 8 or above, we have new possibilities. Firstly, we have two variations for the nextInt method:

Secondly, and more importantly, we can use the ints method:

2.4. java.util.SplittableRandom

Java 8 has also brought us a really fast generator — the SplittableRandom class.

As we can see in the JavaDoc, this is a generator for use in parallel computations. It’s important to know that the instances are not thread-safe. So, we have to take care when using this class.

We have available the nextInt and ints methods. With nextInt we can set directly the top and bottom range using the two parameters invocation:

This way of using checks that the max parameter is bigger than min. Otherwise, we’ll get an IllegalArgumentException. However, it doesn’t check if we work with positive or negative numbers. So, any of the parameters can be negative. Also, we have available one- and zero-parameter invocations. Those work in the same way as we have described before.

We have available the ints methods, too. This means that we can easily get a stream of int values. To clarify, we can choose to have a limited or unlimited stream. For a limited stream, we can set the top and bottom for the number generation range:

2.5. java.security.SecureRandom

If we have security-sensitive applications, we should consider using SecureRandom. This is a cryptographically strong generator. Default-constructed instances don’t use cryptographically random seeds. So, we should either:

  • Set the seed — consequently, the seed will be unpredictable
  • Set the java.util.secureRandomSeed system property to true

This class inherits from java.util.Random. So, we have available all the methods we saw above. For example, if we need to get any of the int values, then we’ll call nextInt without parameters:

On the other hand, if we need to set the range, we can call it with the bound parameter:

We must remember that this way of using it throws IllegalArgumentException if the parameter is not bigger than zero.

How can this be useful ?

Sometimes, the test fixture does not really matter to the test logic. For example, if we want to test the result of a new sorting algorithm, we can generate random input data and assert the output is sorted, regardless of the data itself:

@org.junit.Test
public void testSortAlgorithm() {

   // Given
   int[] ints = easyRandom.nextObject(int[].class);

   // When
   int[] sortedInts = myAwesomeSortAlgo.sort(ints);

   // Then
   assertThat(sortedInts).isSorted(); // fake assertion

}

Another example is testing the persistence of a domain object, we can generate a random domain object, persist it and assert the database contains the same values:

@org.junit.Test
public void testPersistPerson() throws Exception {
   // Given
   Person person = easyRandom.nextObject(Person.class);

   // When
   personDao.persist(person);

   // Then
   assertThat("person_table").column("name").value().isEqualTo(person.getName()); // assretj db
}

There are many other uses cases where Easy Random can be useful, you can find a non exhaustive list in the wiki.

Latest news

  • 15/11/2020: Easy Random v5.0.0 is out and is now based on Java 11. Feature wise, this release is the same as v4.3.0. Please check the release notes for more details.
  • 07/11/2020: Easy Random v4.3.0 is now released with support for generic types and fluent setters! You can find all details in the change log.

What is Easy Random ?

EasyRandom easyRandom = new EasyRandom();
Person person = easyRandom.nextObject(Person.class);

The method is able to generate random instances of any given type.

What is this EasyRandom API ?

The API provides 7 methods to generate random data: , , , , , and .
What if you need to generate a random ? Or say a random instance of your domain object?
Easy Random provides the API that extends with a method called .
This method is able to generate a random instance of any arbitrary Java bean.

The class is the main entry point to configure instances. It allows you to set all
parameters to control how random data is generated:

EasyRandomParameters parameters = new EasyRandomParameters()
   .seed(123L)
   .objectPoolSize(100)
   .randomizationDepth(3)
   .charset(forName("UTF-8"))
   .timeRange(nine, five)
   .dateRange(today, tomorrow)
   .stringLengthRange(5, 50)
   .collectionSizeRange(1, 10)
   .scanClasspathForConcreteTypes(true)
   .overrideDefaultInitialization(false)
   .ignoreRandomizationErrors(true);

EasyRandom easyRandom = new EasyRandom(parameters);

For more details about these parameters, please refer to the configuration parameters section.

In most cases, default options are enough and you can use the default constructor of .

Easy Random allows you to control how to generate random data through the interface and makes it easy to exclude some fields from the object graph using a :

EasyRandomParameters parameters = new EasyRandomParameters()
   .randomize(String.class, () -> "foo")
   .excludeField(named("age").and(ofType(Integer.class)).and(inClass(Person.class)));

EasyRandom easyRandom = new EasyRandom(parameters);
Person person = easyRandom.nextObject(Person.class);

In the previous example, Easy Random will:

  • Set all fields of type to (using the defined as a lambda expression)
  • Exclude the field named of type in class .

The static methods , and are defined in
which provides common predicates you can use in combination to define exactly which fields to exclude.
A similar class called can be used to define which types to exclude from the object graph.
You can of course use your own in combination with those predefined predicates.

Why Easy Random ?

Populating a Java object with random data can look easy at first glance, unless your domain model involves many related classes. In the previous example, let’s suppose the type is defined as follows:

Without Easy Random, you would write the following code in order to create an instance of the class:

Street street = new Street(12, (byte) 1, "Oxford street");
Address address = new Address(street, "123456", "London", "United Kingdom");
Person person = new Person("Foo", "Bar", "foo.bar@gmail.com", Gender.MALE, address);

And if these classes do not provide constructors with parameters (may be some legacy beans you can’t change), you would write:

Street street = new Street();
street.setNumber(12);
street.setType((byte) 1);
street.setName("Oxford street");

Address address = new Address();
address.setStreet(street);
address.setZipCode("123456");
address.setCity("London");
address.setCountry("United Kingdom");

Person person = new Person();
person.setFirstName("Foo");
person.setLastName("Bar");
person.setEmail("foo.bar@gmail.com");
person.setGender(Gender.MALE);
person.setAddress(address);

With Easy Random, generating a random object is done with .
The library will recursively populate all the object graph. That’s a big difference!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector