Java Match.random не правильно вычисляет при одинаковых min , max

Метод для вычисления рандомного значения числа.
Если я передаю минимальное и максимальное значение одинаковым, в моем случае это 1.9, то в ответ я всегда получаю 1.8. Подскажите, почему так? И как исправить?

public static String random(String m, String mx, int scale) {
    
    Double min = Double.parseDouble(m);
    Double max = Double.parseDouble(mx);
    Double res;
    String rs = "";
    
    res = new BigDecimal((Math.random() * (max - min)) + min).setScale(scale, RoundingMode.FLOOR).doubleValue();

    if(scale == 0) {
        rs = new DecimalFormat("#0").format(res).replace(",", ".");
    }
    else if(scale == 1) {
        rs = new DecimalFormat("#0.0").format(res).replace(",", ".");
    }else if(scale ==2) {
        rs = new DecimalFormat("#0.00").format(res).replace(",", ".");
    }

    return rs;
}

Ответы (1 шт):

Автор решения: Nowhere Man

Всё дело в выбранном режиме округления в методе setScale, см. документацию перечисления RoundingMode

Поскольку выбран режим RoundingMode.FLOOR, будет выполняться округление по направлению к -∞, и для переменной точности, заданной параметром scale, округление будет выполняться для соответствующего разряда.

Если добавить параметр RoundingMode к представленному методу, можно написать небольшой тест:

import java.math.*;
import java.text.*;

public class MyClass {
    
    public static String random(String mn, String mx, int scale, RoundingMode roundMode) {
        Double min = Double.parseDouble(mn);
        Double max = Double.parseDouble(mx);
        Double res = new BigDecimal((Math.random() * (max - min)) + min).setScale(scale, roundMode).doubleValue();
    
        if (scale == 0) {
            return new DecimalFormat("#0").format(res).replace(",", ".");
        }
        return new DecimalFormat("#0." + "0".repeat(scale)).format(res).replace(",", ".");
    }

    public static void main(String args[]) {
        System.out.println("| scale | FLOOR | CEILING | HALF_DOWN | HALF_UP | HALF_EVEN |");
        System.out.println("|-------|-------|---------|-----------|---------|-----------|");
        for (int scale = 0; scale < 4; scale++) {
            System.out.printf("|   %d   | %-5s |   %-5s |    %-6s |   %-5s |    %-6s |%n", 
                scale, 
                random("1.9", "1.9", scale, RoundingMode.FLOOR),
                random("1.9", "1.9", scale, RoundingMode.CEILING),
                random("1.9", "1.9", scale, RoundingMode.HALF_DOWN),
                random("1.9", "1.9", scale, RoundingMode.HALF_UP),
                random("1.9", "1.9", scale, RoundingMode.HALF_EVEN)
            );
        }
    }
}

Результат:

| scale | FLOOR | CEILING | HALF_DOWN | HALF_UP | HALF_EVEN |
|-------|-------|---------|-----------|---------|-----------|
|   0   | 1     |   2     |    2      |   2     |    2      |
|   1   | 1.8   |   1.9   |    1.9    |   1.9   |    1.9    |
|   2   | 1.89  |   1.90  |    1.90   |   1.90  |    1.90   |
|   3   | 1.899 |   1.900 |    1.900  |   1.900 |    1.900  |
→ Ссылка