4

У меня есть строка в мой код так же, как показано ниже:округлить с плавающей точкой в ​​Java

float rand = (float) Math.random(); 

Math.random() возвращает двойной, который >=0.0 и <1.0. К сожалению, литой выше может установить rand в 1.0f, если двойной слишком близко к 1.0.

Есть ли способ бросить двойное поплавок таким образом, чтобы при отсутствии точного равного значения он всегда округлялся до следующего значения плавающей позиции, а не до ближайшего значения поплавка?

Я не ищу советы по RNG, а также обходные вопросы, например, следующие: if(rand == 1.0f) rand = 0.0f;. В моем случае это решение является удовлетворительным способом устранения моей проблемы, и оно уже реализовано. Я просто заинтересован в поиске «правильного» решения такого рода преобразования чисел.

+0

Есть причина, вы не можете использовать [nextFloat()] (https://docs.oracle.com/javase/8/docs/api/java/util/Random.html#nextFloat--)? – VGR

ответ

1

Если вы хотите только округлить, когда rand==1.0f, то я отвечу на второй @ paxdiablo. Тем не менее, похоже, что вы в порядке, всегда округляя, и просто хотите всегда округлять вниз. Если это так:

float rand = Math.nextDown((float)Math.random()); 

от Javadoc:

nextDown (флоат е) Возвращает значение с плавающей запятой, примыкающий к F в направлении отрицательной бесконечности.

В ответ на ваш комментарий - хороший момент. Чтобы избежать этой проблемы, вы можете просто обернуть оператор при вызове Math.abs(), который не будет иметь никакого влияния, кроме случаев, когда результат nextDown() отрицательный.

float rand = Math.abs(Math.nextDown((float)Math.random())); 
+1

Это хорошая полезная находка! Однако было бы плохо, если бы вызов Math.random() возвращал 0.0, поскольку он нажимал бы его ниже 0 – Numeron

+0

@Numeron - хорошая точка, см. Edit – drewmoore

+0

Я думаю, что если я использую что-то вроде «if (doubleRand! = FloatRand) floatRand = Math.nextDown (floatRand);» - поэтому он только понижает значение, когда нет равного эквиваланта. – Numeron

1

Вариант, который я бы предложил, будет использовать double, а не float.

Единственные недостатки, которые я когда-либо обнаружил, вступают в игру только в том случае, если у вас их большое количество, поскольку требования к хранению выше, и это, похоже, не так.

Если вы должны использовать float, то решение, которое вы уже пробовали, возможно, является лучшим из доступных. Это фундаментальная проблема, что потеря точности при преобразовании double в float может дать вам 1.0f.

Таким образом, вы можете использовать значение float в своем желаемом диапазоне.

Однако, вы не должны перец код с if заявления для этого, просто обеспечивают поплавка случайную функцию, которая делает тяжелую работу за вас:

float frandom() { 
    float ret = 1.0f; 
    while (ret == 1.0f) 
     ret = (float) Math.random(); 
    return ret; 
} 

или, согласно вашему образцу:

float frandom() { 
    float ret = (float) Math.random(); 
    if (ret == 1.0f) 
     ret = 0.0f; 
    return ret; 
} 

затем вызвать его:

float rand = frandom(); 

Это будет пои nt, где было бы хорошо для Java (и других) иметь возможность Javascript «вводить» код в тип, чтобы вы могли реализовать frandom() в статической арене Math. Таким образом, вы могли бы просто использовать:

float rand = Math.frandom(); 

Но, увы, это не представляется возможным (насколько я знаю, не хватает перекомпиляции библиотеки поддержки Java, которая кажется немного излишним).


Кстати, если вы ищете для максимального значения с плавающей точкой меньше 1, это 0.99999994 (показатель степени, мультипликатор 2-1 со всеми мантиссами бит, установленных в 1), так что вы можете использовать, что вместо 0.0f в функции frandom() выше.

Это почерпнуто из удобного инструмента, который я написал некоторое время назад, который оказался неоценимым, когда он играл с плавающей точкой IEEE754.

+0

Да, это в основном то, что у меня уже есть. Вопрос, который я хочу знать, заключается в том, как преобразовать double в float, округляя до следующего значения, а не до ближайшего доступного. – Numeron

+0

Только для науки. Моя непосредственная проблема уже решена. – Numeron

+1

Должно ли '0,1' быть' 1.0'? – immibis

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