2015-06-02 5 views
1

Я обнаружил, что Random#nextFloat возвращает значение между 0.0 и 1.0.Как я могу получить значения случайных чисел с плавающей запятой?

Как получить случайное значение поплавка, например -72.0F или 126.232F?

Я сейчас занимаюсь этим.

float randomFloat() { 
    final ThreadLocalRandom random = ThreadLocalRandom.current(); 
    float value = random.nextFloat() * Float.MAX_VALUE; 
    if (random.nextBoolean()) { 
     value = 0 - value; 
    } 
    return value; 
} 

Это право? Есть ли другой способ сделать это?

+1

Я думаю, вы могли бы вызвать 'random.nextInt()', а затем использовать 'Float.intBitsToFloat()'. Однако это может быть не так случайным, как вам хотелось бы, и вам, возможно, придется иметь дело с ошибками формата в битовых шаблонах. – markspace

ответ

2

Я хотел бы предложить генерации связанное дважды, а затем преобразовать, чтобы плавать:

return Double.valueOf(random.nextDouble(Float.MIN_VALUE, Float.MAX_VALUE)).floatValue(); 

nextDouble метод был заменен в Java 8 с методом, чтобы получить поток двойников. Таким образом, в Java 8 вы должны использовать следующий эквивалент:

DoubleStream randomDoubles = new Random().doubles(Float.MIN_VALUE, Float.MAX_VALUE); 
Double.valueOf(randomDoubles.findAny().getAsDouble()).floatValue(); 
+0

Это не может вызвать отрицательные числа. Кроме того, если 'random' является java.util.Random, он не имеет этого метода в JDK 1.8. –

+0

@PatriciaShanahan Я тестировал это, и он с радостью производит отрицательные числа - я не уверен, где вы получили представление о том, что он не создает негативов. Существует эквивалентный метод в Java 8: 'doubleles', который создает поток двойников. Я добавлю версию Java 8 в ответ. – sprinter

+0

Проблема в том, что Random.doubles() или random.nextDouble() использует равномерно выбранные двойные значения между 0 и 1, а затем масштабирует их, чтобы они соответствовали границам. Это означает, что некоторые значения будут отсутствовать, а некоторые значения будут появляться чаще, чем другие (хотя в целом гистограмма, скорее всего, не покажет это). @markspace имеет правильную идею. – llogiq

2

Это основано на общей идее в prior answer, но фиксирует небольшую ошибку и показывает, как на самом деле написать метод с использованием JDK 1.8:

import java.util.Iterator; 
import java.util.concurrent.ThreadLocalRandom; 

public class Test { 
    public static void main(String[] args) { 
    Test t = new Test(); 
    for (int i = 0; i < 100; i++) { 
     System.out.println(t.randomFloat()); 
    } 
    } 

    final ThreadLocalRandom random = ThreadLocalRandom.current(); 
    Iterator<Double> randomDoubles = random.doubles(-Float.MAX_VALUE, 
     Math.nextUp((double) Float.MAX_VALUE)).iterator(); 
    float randomFloat() { 
    return randomDoubles.next().floatValue(); 
    } 
} 

Код в вопроснике ThreadLocalRandom, поэтому я сделал то же самое. Метод Random doubles исключает верхний предел. Чтобы получить требуемый полный диапазон, используйте в качестве предела наименьший двойник, который больше, чем все конечные значения float. Получение iterator<Double> показалось простым и более прямым, чем использование findAny и т. Д.

+0

Хороший ответ и хорошая идея преобразования потока в итератор. – sprinter

Смежные вопросы