What is the best way to generate a random float value included into a specified value interval?

69,789

Solution 1

For a random value within a range, the formula is:

double random = min + Math.random() * (max - min);

This basic formula is constant no matter what you use to generate random numbers.

Math.random() provides moderately well distributed numbers, but you can replace it with whatever random number generator you want, for example (slightly better):

Random r = new Random();
double random = min + r.nextDouble() * (max - min);

or if you really want a float:

float random = min + r.nextFloat() * (max - min);

For a better quality (at the cost of speed) random number generation use

Random random = new SecureRandom();

Or you can use a more exotic 3rd party library, such as:

import org.apache.commons.math3.random.RandomDataGenerator;

RandomData random = new RandomDataGenerator();

Which uses the superior Well19937c algorithm.

Solution 2

If you want to generate random float values try this:

import java.util.Random;

public static float randFloat(float min, float max) {

    Random rand = new Random();

    return rand.nextFloat() * (max - min) + min;

}

Hope this helped.

Solution 3

I know that this question is over a year old, but the other answers here are missing important points. The best way to generate a random floating-point value in Java (assuming you don't need a specific seed and you don't need to be cryptographically secure) is the ThreadLocalRandom class.

For example, if you want a method that generates random numbers between two other numbers, you could write it like this:

public static double generateRandomDouble(double min, double max) {
  return ThreadLocalRandom.current().nextDouble(min, max);
}
  • The problem with Math.random is that it results in contention. In other words, if your code is being run concurrently with any other code that uses Math.random, your random number may have to be recomputed.
  • The problem with new Random() is that it's creating a new Random instance every time it's called, which is extra work and more verbose.
  • The problem with both of these methods is that they force you to do the extra math to scale it to the desired range, making your code less readable and more error-prone. The ThreadLocalRandom class has a very convenient nextDouble overload that lets you specify an "origin" and "bound," meaning minimum and maximum.
  • Another problem with both of these methods is that they're imprecise. Because you're doing the scaling, you need to account for the rounding problems that are inherent in floating-point arithmetic. In fact, all of the other answers to this question will sometimes produce answers equal to max.

In the code above, I am making two assumptions. First, you want the lower bound to be inclusive and the upper bound to be exclusive. This assumption is rather trivial, because the probability of actually landing on the boundary is very small. This is also what the other answers are attempting to do (though they sometimes produce answers equal to max, unlike mine). The second assumption I make is that by a "random float value," you mean a floating-point value, which I assumed based on the fact that you tagged the question with . Thus, I gave a method that returns a double, which is a double-precision floating-point value, and what you'll typically use in Java for floating-point values. However, if you meant to specify a float primitive, you can use the following method:

public static float generateRandomFloat(float min, float max) {
  if (min >= max)
    throw new IllegalArgumentException("max must be greater than min");
  float result = ThreadLocalRandom.current().nextFloat() * (max - min) + min;
  if (result >= max) // correct for rounding
    result = Float.intBitsToFloat(Float.floatToIntBits(max) - 1);
  return result;
}

There is unfortunately no nextFloat overload on ThreadLocalRandom, presumably because they expect very few people to need random floats. To write this method correctly, you must correct for floating-point rounding problems. Thus, I would strongly recommend that you use the version that produces a double.

In conclusion, you should never use Math.random, and you shouldn't create a new Random instance every time you need to generate a random number (unless, of course, you need a specific seed). When generating random numbers, default to the ThreadLocalRandom class.

Solution 4

Code:

import java.util.Scanner;


public class Hello 
{

    public static void main(String[] args)
    {       

        Scanner sc=new Scanner(System.in);

        double max,min,randfloat;

        System.out.println("Enter minimum :");
        min=sc.nextDouble();
        System.out.println("Enter maximum :");
        max=sc.nextDouble();    

        randfloat=(Math.random())*(max-min)+min; //Math.random() generates random value between 0 and 1

        System.out.println("Random float value generated is: "+randfloat);
        sc.close();

    }

}

Example

Share:
69,789
AndreaNobili
Author by

AndreaNobili

Updated on January 06, 2021

Comments

  • AndreaNobili
    AndreaNobili over 3 years

    I want to generate a random float value in Java. The value has to be within a specific range of possible values.

    For example, I have to generate a random value that is in the following range:

    MIN: 41,815080
    MAX: 41,829191
    

    These values happen to represent a range of possible longitudes on a map, but the question applies more generally.

    What is a smart way to do it?

  • Paul
    Paul over 7 years
    this will neither compile, nor work properly. You need to return a value and the returned value should be of type float, not int.
  • truthadjustr
    truthadjustr about 4 years
    How about if including negative float values?
  • Bohemian
    Bohemian about 4 years
    @truthadjustr what about them? This code works for all values of max and min, positive or negative. Note that -1 is greater than -2.
  • truthadjustr
    truthadjustr about 4 years
    Between the range of -3 to +3, so the snippet becomes r.nextFloat() * (3 - (-3)) would produce a negative value? Here, max is 3 and min is -3.
  • Bohemian
    Bohemian about 4 years
    @truthadjustr incorrect. If min is -3 and max is +3, then max - min is 3 - -3 which is 3 + 3 which is 6, which common sense tells you is the distance from -3 to +3. So, the whole expression is then -3 + r.nextFloat() * 6. On average, half the values produced will be negative (between -3 and zero).
  • ghost_programmer
    ghost_programmer about 4 years
    max and min are inclusive or exclusive?
  • Bohemian
    Bohemian about 4 years
    @MuhammadAshfaq as with all C-like languages, min is inclusive, max is exclusive. In the case of floating point values, "max being exclusive" means it can be almost, but not quite the max, eg. if the max is 3, the largest values would be 2.999999
  • Luke Hutchison
    Luke Hutchison almost 3 years
    You can't generate random doubles over very large ranges this way, if max is large and min is small or zero. r.nextDouble() * (Double.MAX_VALUE - 0.0) will deliver only random numbers around the 1.0e307 to 1.0e308 range, nothing smaller.
  • Bohemian
    Bohemian almost 3 years
    @LukeHutchison true. It fails to behave well for all |min| + |max| > Double.MAX_VALUE, with increasing misbehaviour the larger the sum. I have never been in a situation that used such ranges, nor can I imagine one, however If writing function for this, you could check that the range does not exceed this limit, or more simply require min to be non-negative, or just declare in the javadoc your that this edge case is not catered for.
  • Luke Hutchison
    Luke Hutchison almost 3 years
    @Bohemian that's not the correct diagnosis, since |0.0| + |Double.MAX_VALUE| == Double.MAX_VALUE. It's not greater. The actual problem has to do with how r.nextDouble() works: it calculates a fractional part with 53 random bits, but the exponent is zero. So the smallest nonzero random number it generates is 1/(1<<53). docs.oracle.com/javase/8/docs/api/java/util/…