• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Liutauras Vilda
  • Ron McLeod
  • Jeanne Boyarsky
  • Paul Clapham
Sheriffs:
  • Junilu Lacar
  • Tim Cooke
Saloon Keepers:
  • Carey Brown
  • Stephan van Hulst
  • Tim Holloway
  • Peter Rooke
  • Himai Minh
Bartenders:
  • Piet Souris
  • Mikalai Zaikin

Generate random floating point numbers from min (inclusive) to max (inclusive)

 
Ranch Hand
Posts: 281
jQuery MySQL Database PHP
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I try to write a method of creating random floating point number from min (inclusive) to max (inclusive). After that, I tried to run 1 loop 1 billion times with that method:

After testing several times, both methods didn't return to the maximum value. After that, I reread the document on the method of nextFloat():

The general contract of nextFloat is that one float value, chosen (approximately) uniformly from the range 0.0f (inclusive) to 1.0f (exclusive)...


According to the document, I will never get a value of 1.0, so I can't get:  return 1.0 * max;
So, I want to know some solution for this case.
 
Marshal
Posts: 27675
89
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
In your desired distribution, what is the probability of 1.0 occurring?
 
Marshal
Posts: 77957
373
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tan Quang wrote:. . . After that, I reread the document . . .

Just think how much trouble you would have saved yourself if you had read the documentation first. Never go round thinking you know what a method does, nor make any assumptions about its behaviour.

So, I want to know some solution for this case.

My first recommendation would be only to use floats when some other code, for example this constructor, forces you to.
I would suggest you won't be able to achieve an inclusive‑inclusive range reliably at all. You could try converting the floating‑point number to its corresponding integer value, adding 1, and converting it back to floating‑point. I think that will be a very error‑prone action, which will definitely not work for negative arguments. It will probably also fail for MAX_VALUE, ∞, and NaNs. Otherwise you could try looking at pseudorandom number algorithms and write your own random generator.
 
Bartender
Posts: 5368
212
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well, chance of getting that max is practically 0, anyway.
But a way would be to use Math.nextAfter(max, max + 1) and use it like:

As Campbell writes: the use of doubles is much easier, although you could cast your doubles to floats.
 
Paul Clapham
Marshal
Posts: 27675
89
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:I would suggest you won't be able to achieve an inclusive‑inclusive range reliably at all.


If the question had been about random double values, I would agree with you. But if there are N different float values in [0, 1) then the question is to return random values from the N + 1 floats in [0, 1]. Which it's possible to do with the help of random doubles.
 
Campbell Ritchie
Marshal
Posts: 77957
373
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Paul Clapham wrote:. . . If the question had been about random double values . . . .

It simply said, “floating point” in the thread title, and I assumed the use of floats was to allow the loop to run in less time than the OP's whole lifetime. Yes, you could use doubles with a cast to a float, but that brings me out in spots even worse than plain simple floats
 
Campbell Ritchie
Marshal
Posts: 77957
373
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I wasn't familiar with Math#nextAfter() before; thank you, Piet. That looks a better option than my adding 1.
 
Piet Souris
Bartender
Posts: 5368
212
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You're welcome!
 
Tan Quang
Ranch Hand
Posts: 281
jQuery MySQL Database PHP
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Paul Clapham wrote:In your desired distribution, what is the probability of 1.0 occurring?


Because (in fairness) this is a random number function, so the probability of creating its number is random, there is no priority for any results!
 
Tan Quang
Ranch Hand
Posts: 281
jQuery MySQL Database PHP
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:Just think how much trouble you would have saved yourself if you had read the documentation first. Never go round thinking you know what a method does, nor make any assumptions about its behaviour.


It's not that I have not read the document, but it's been a long time since I last to read the document about this method. So I had a little confusion between (IN)clusive and (EX)clusive.

My first recommendation would be only to use floats when some other code, for example this constructor, forces you to.
I would suggest you won't be able to achieve an inclusive‑inclusive range reliably at all. You could try converting the floating‑point number to its corresponding integer value, adding 1, and converting it back to floating‑point. I think that will be a very error‑prone action, which will definitely not work for negative arguments. It will probably also fail for MAX_VALUE, ∞, and NaNs. Otherwise you could try looking at pseudorandom number algorithms and write your own random generator.


Yes, my main desire is to create random numbers in the most "perfect" way (I have not yet come up with the most alternative words). If I create a random integer, it looks pretty "rough", and if I create a double random number, the results I get will be very longggggg (unnecessarily)...
 
Tan Quang
Ranch Hand
Posts: 281
jQuery MySQL Database PHP
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Piet Souris wrote:Well, chance of getting that max is practically 0, anyway.


Yes, nextFloat() will return the "random" number between 0 to 0.9999999, will never get the result of 1.0!

But a way would be to use Math.nextAfter(max, max + 1) and use it like:

As Campbell writes: the use of doubles is much easier, although you could cast your doubles to floats.


Campbell Ritchie wrote:I wasn't familiar with Math#nextAfter() before; thank you, Piet. That looks a better option than my adding 1.


I have never used Math#nextAfter() before. I think I will study a little about it!
 
Tan Quang
Ranch Hand
Posts: 281
jQuery MySQL Database PHP
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:It simply said, “floating point” in the thread title, and I assumed the use of floats was to allow the loop to run in less time than the OP's whole lifetime. Yes, you could use doubles with a cast to a float, but that brings me out in spots even worse than plain simple floats


Yes, the request of this topic (mine) is float, not double. It is also not used to calculate the modules, so it does not need to be "absolutely accurate".
I simply want to get a brief and perfect random result. float gave me what I wanted, with integer, it was quite "rough", with double, it was too long unnecessary.
I want 23.5929614 (the length is 7 - perfect) instead of 44.27661040778083 (the length is 16 - too long).
 
Paul Clapham
Marshal
Posts: 27675
89
Eclipse IDE Firefox Browser MySQL Database
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tan Quang wrote:

Paul Clapham wrote:In your desired distribution, what is the probability of 1.0 occurring?


Because (in fairness) this is a random number function, so the probability of creating its number is random, there is no priority for any results!



Well, no, when you call the nextFloat() method it returns a random float number. That means that the probability of returning any float value is 1/N, where N is the number of different float values in [0, 1).

Now you want to select from [0, 1]. There are N+1 float values in that range. So the probability of returning 1 by your code should be 1/(N+1), and so should be the probability of returning any float value below 1.

So what I would do is this: Get a random long value. If it's less than 1/(N+1) then return 1, otherwise return the float value which nextFloat() returns.

I think that answers the question you asked. However I don't think you understand the question, instead you're going off on tangents about how Java represents floating-point numbers, which has little to say about randomness.
 
Tan Quang
Ranch Hand
Posts: 281
jQuery MySQL Database PHP
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Paul Clapham wrote:Well, no, when you call the nextFloat() method it returns a random float number. That means that the probability of returning any float value is 1/N, where N is the number of different float values in [0, 1).

Now you want to select from [0, 1]. There are N+1 float values in that range. So the probability of returning 1 by your code should be 1/(N+1), and so should be the probability of returning any float value below 1.

So what I would do is this: Get a random long value. If it's less than 1/(N+1) then return 1, otherwise return the float value which nextFloat() returns.

I think that answers the question you asked. However I don't think you understand the question, instead you're going off on tangents about how Java represents floating-point numbers, which has little to say about randomness.


You mean it will be like this?

I tried running it:

Surprisingly, the frequency of 1.0 is always in the range of 104 ~ 132 times / 1 billion.

Paul Clapham wrote:...
Now you want to select from [0, 1]. There are N+1 float values in that range. So the probability of returning 1 by your code should be 1/(N+1), and so should be the probability of returning any float value below 1.

So what I would do is this: Get a random long value. If it's less than 1/(N+1) then return 1, otherwise return the float value which nextFloat() returns....


And as I tested, it never appeared valuable results greater than 1.0!
 
Paul Clapham
Marshal
Posts: 27675
89
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tan Quang wrote:You mean it will be like this?



That's not in any way related to what I posted, no.

Your values "RAND.nextFloat()" are in the range [0, 1). If you add 1 (as you did) then you get numbers in the range [1, 2). If you then take their reciprocals (as you did) then you get numbers in the range (0.5, 1].

So yeah, you'll get 1 as the result occasionally. With the same frequency as any other value in the range, actually. And no, you won't ever get a number greater than 1.
 
Piet Souris
Bartender
Posts: 5368
212
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Paul means this (I reckon. If not, he will correct me):

suppose there are four floats between 0 and 1: 0f, 0.25f. 0.50f and 0.75f.
Then N = 4, N + 1 = 5, and the procedure would be:

draw a double (I assume, Paul mentions a long), and if that double < 1/5 return 1, else return the float. Now, two problems with that:

1) how to calculate N? I tried two ways, but the outcomes differed a factor 1000. Perhaps looking at the specs of a float might give the correct answer.

2) and if we suppose that random.nextDouble() IS uniformly distributed, then what are the chances of getting 0f, .25f, .5f, .75f or 1f?

 
Master Rancher
Posts: 4457
60
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
[composed mostly before seeing Piet's reply]

Paul Clapham wrote:That's not in any way related to what I posted, no.


It is related, in the sense that it's the result of incorrectly applying the formula you gave, in a way that will yield a very different probability distribution than what was desired.

Tan Quang: When Paul referred to "1/(1+N)", "N" meant the number of different possible values that you expect to be able to return.  N is not, repeat NOT, the return value of Random.nextFloat().  That would be very different.  The formula

1 / (RAND.nextFloat() + 1)

gives a value in the range (0.5,1] - and also importantly, it's no longer a uniform distribution.  Taking the reciprocal is not a linear operation.  If you look at how many value are in (0.5,0.6] and compare to how many are in (0.9,1], you will find the counts are consistently rather different.

Which doesn't really matter - the formula was not what Paul was saying, anyway.

I suggest the following, a different formulation which I believe is pretty close to what Paul was saying:

Now, I took my definition of N from the API for Random.nextFloat().  But, you could also legitimately try very different values - and you will find the chance of getting 1.0f exactly can vary quite a bit.  Which goes back to Paul's original comment - you need to decide how many discrete values you want your distribution to be able to return.  It's an arbitrary choice you get to make, which directly affects the results.
 
Also related is the fact that floating-point arithmetic is inherently imprecise, and if your code depends very much on whether a value is exactly equal to a given floating-point value (rather than close to or greater / less than that value) then your program is probably asking for trouble.  It's hard to imagine an application where this function would do something useful, that's significantly different from the results you'd get from Random.nextFloat().
 
Paul Clapham
Marshal
Posts: 27675
89
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Piet Souris wrote:Paul means this (I reckon. If not, he will correct me):

suppose there are four floats between 0 and 1: 0f, 0.25f. 0.50f and 0.75f.
Then N = 4, N + 1 = 5, and the procedure would be:

draw a double (I assume, Paul mentions a long), and if that double < 1/5 return 1, else return the float. Now, two problems with that:

1) how to calculate N? I tried two ways, but the outcomes differed a factor 1000. Perhaps looking at the specs of a float might give the correct answer.

2) and if we suppose that random.nextDouble() IS uniformly distributed, then what are the chances of getting 0f, .25f, .5f, .75f or 1f?



That is what I meant (and yes, I should have said double and not long). But there is no mystery about how to calculate N, the API documentation for Random.nextFloat() tells us exactly what it is.

Likewise the docs for Random.nextDouble say that the result is "(approximately) uniformly" distributed. So 1/5 of the time (approximately) that algorithm returns 1. And 4/5 of the time it returns a value chosen randomly (and uniformly) from the set 0f, 0.25f. 0.50f and 0.75f. This means that each of those four values are chosen with probability 4/5 * 1/4 = 1/5.
 
Paul Clapham
Marshal
Posts: 27675
89
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:It's hard to imagine an application where this function would do something useful, that's significantly different from the results you'd get from Random.nextFloat().



I remember a post from several years ago which asked a question much like this. The poster's boss didn't like the idea that random numbers were chosen from the range [0, 1) and wanted 1.0 to be chosen sometimes. At least that is how I remember it in general. There was no information about why the boss wanted that, but it's often useful to write code which satisfies a boss's requirement even if said requirement is not actually of any use.
 
Mike Simmons
Master Rancher
Posts: 4457
60
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
To be fair, the fact that the value of N is specified for Random.nextFloat() does not mean that this is the only possible correct value.  This is a new method with a different API; it can have a different value of N if desired.  The fact that this is in fact an arbitrary choice that makes a big difference (at least for the probability of result == 1.0F) is a clue that the whole project is of questionable value.
 
Mike Simmons
Master Rancher
Posts: 4457
60
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Paul Clapham wrote:it's often useful to write code which satisfies a boss's requirement even if said requirement is not actually of any use.


Yeah, true.  Also, there can indeed be real-world cases where you want the max value to occasionally appear, and people will notice and complain if that doesn't happen.  But it really only would happen in cases where the outputs are sufficiently limited to a set of discrete values, enough so that 1/(N+1) is significantly different from 0.  But in such cases, it's probably better to use nextInt() or nextLong() to control exactly what the values will be.

By the way, here's another version - similar idea, with a different value set (that may or may not matter):
 
Mike Simmons
Master Rancher
Posts: 4457
60
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Here's one more like Paul's original instructions - corrected a different way than Piet did:

I believe it's equivalent to my original code, as long as N=1<<24 to match what's used in nextFloat().  My original code allows smoothly changing N to any other value desired, as well.  My second code with CORRECTION_RATIO is different, giving N possible values, rather than N + 1, spread evenly over [0,1].
 
Piet Souris
Bartender
Posts: 5368
212
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Paul Clapham wrote:But there is no mystery about how to calculate N, the API documentation for Random.nextFloat() tells us exactly what it is.

You are right. Seems I've never read that information!    
 
Tan Quang
Ranch Hand
Posts: 281
jQuery MySQL Database PHP
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Paul Clapham wrote:That's not in any way related to what I posted, no.

Your values "RAND.nextFloat()" are in the range [0, 1). If you add 1 (as you did) then you get numbers in the range [1, 2). If you then take their reciprocals (as you did) then you get numbers in the range (0.5, 1].

So yeah, you'll get 1 as the result occasionally. With the same frequency as any other value in the range, actually. And no, you won't ever get a number greater than 1.


Yes, I also realized that the results returned something wrong...
 
Tan Quang
Ranch Hand
Posts: 281
jQuery MySQL Database PHP
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Piet Souris wrote:Paul means this (I reckon. If not, he will correct me):

suppose there are four floats between 0 and 1: 0f, 0.25f. 0.50f and 0.75f.
Then N = 4, N + 1 = 5, and the procedure would be:

draw a double (I assume, Paul mentions a long), and if that double < 1/5 return 1, else return the float. Now, two problems with that:

1) how to calculate N? I tried two ways, but the outcomes differed a factor 1000. Perhaps looking at the specs of a float might give the correct answer.

2) and if we suppose that random.nextDouble() IS uniformly distributed, then what are the chances of getting 0f, .25f, .5f, .75f or 1f?


All I want is random with all results, no priority for any results!
 
Tan Quang
Ranch Hand
Posts: 281
jQuery MySQL Database PHP
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:[composed mostly before seeing Piet's reply]

Paul Clapham wrote:That's not in any way related to what I posted, no.


It is related, in the sense that it's the result of incorrectly applying the formula you gave, in a way that will yield a very different probability distribution than what was desired.

Tan Quang: When Paul referred to "1/(1+N)", "N" meant the number of different possible values that you expect to be able to return.  N is not, repeat NOT, the return value of Random.nextFloat().  That would be very different.  The formula

1 / (RAND.nextFloat() + 1)

gives a value in the range (0.5,1] - and also importantly, it's no longer a uniform distribution.  Taking the reciprocal is not a linear operation.  If you look at how many value are in (0.5,0.6] and compare to how many are in (0.9,1], you will find the counts are consistently rather different.

Which doesn't really matter - the formula was not what Paul was saying, anyway.

I suggest the following, a different formulation which I believe is pretty close to what Paul was saying:

Now, I took my definition of N from the API for Random.nextFloat().  But, you could also legitimately try very different values - and you will find the chance of getting 1.0f exactly can vary quite a bit.  Which goes back to Paul's original comment - you need to decide how many discrete values you want your distribution to be able to return.  It's an arbitrary choice you get to make, which directly affects the results.
 
Also related is the fact that floating-point arithmetic is inherently imprecise, and if your code depends very much on whether a value is exactly equal to a given floating-point value (rather than close to or greater / less than that value) then your program is probably asking for trouble.  It's hard to imagine an application where this function would do something useful, that's significantly different from the results you'd get from Random.nextFloat().


As I explained earlier, this method MUST NOT be used to calculate important cases.
Simply put it is like in the coin toss game, you have 42.58% toss out the head of the coin, if you get a bigger result then return it to the tail. So the type of data that needs high accuracy like double is really not necessary.
So what I need is:

What I don't need:

So, I hope you understand what I'm saying!
 
Tan Quang
Ranch Hand
Posts: 281
jQuery MySQL Database PHP
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:Here's one more like Paul's original instructions - corrected a different way than Piet did:

I believe it's equivalent to my original code, as long as N=1<<24 to match what's used in nextFloat().  My original code allows smoothly changing N to any other value desired, as well.  My second code with CORRECTION_RATIO is different, giving N possible values, rather than N + 1, spread evenly over [0,1].


Looking at your code is like if the random result is 0, I will receive 1. Therefore, I will never get 0... it's like (0, 1]?
 
Paul Clapham
Marshal
Posts: 27675
89
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tan Quang wrote:So, I hope you understand what I'm saying!



Not really. But perhaps I'm looking at it from a mathematical point of view whereas you have a more aesthetic idea.
 
Paul Clapham
Marshal
Posts: 27675
89
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tan Quang wrote:Looking at your code is like if the random result is 0, I will receive 1. Therefore, I will never get 0... it's like (0, 1]?



No, Mike's code almost always returns Random.nextFloat(), which returns zero as often as it returns any other value in the range [0, 1).
 
Mike Simmons
Master Rancher
Posts: 4457
60
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yup.  1/(N+1) of the time, it returns 1.  The remaining N/(N+1) of the time, it returns RAND.nextFloat(), which covers [0,1).  Between the two, it covers [0,1] uniformly (in the way Paul was originally describing).
 
Tan Quang
Ranch Hand
Posts: 281
jQuery MySQL Database PHP
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:

Paul Clapham wrote:it's often useful to write code which satisfies a boss's requirement even if said requirement is not actually of any use.


Yeah, true.  Also, there can indeed be real-world cases where you want the max value to occasionally appear, and people will notice and complain if that doesn't happen.  But it really only would happen in cases where the outputs are sufficiently limited to a set of discrete values, enough so that 1/(N+1) is significantly different from 0.  But in such cases, it's probably better to use nextInt() or nextLong() to control exactly what the values will be.

By the way, here's another version - similar idea, with a different value set (that may or may not matter):


The ratio about of 56 /1 billion with 0 and 64 /1 billion with 1.
Basically it looks quite similar to the source code of the nextFloat() method, except data type of N is int (not long) and CORRECTION_RATIO  is float (not double) in source code!
 
Mike Simmons
Master Rancher
Posts: 4457
60
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tan Quang wrote:The ratio about of 56 /1 billion with 0 and 64 /1 billion with 1.


Where do those numbers come from?  Measured results, or somewhere else?  If measurements, have you repeated the measurements enough to see if it's consistent?
 
Mike Simmons
Master Rancher
Posts: 4457
60
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tan Quang wrote:All I want is random with all results, no priority for any results!


That sounds reasonable - but you have to realize, "all results" can be ambiguous here.  In an ideal, purely mathematical world, we have an infinite continuum of real numbers in the range [0,1], and the probability of any one precise number (like 1) is infinitesmally small.  In practice, we are using computer data types which approximate real numbers using a finite set of values.  We can't even say that we want all possible float values to be equally probable - because the float value set is not uniformly distributed.  There are many possible float values between 0.0 and 0.1 than there are between 0.9 and 1.0, for example.  Methods like Random.nextFloat() solve this by restricting themselves to a smaller subset of possible values, but ensuring that those are evenly distributed.  From the API, we learn that all the values are integer multiples of 1/(2^24), which we can write as 1<<24.  Now, you can use a value set like this (adding 1 as a possible value), or you can use a different set - my first method allows you to choose any N you want.

(So when Piet gives an example using 0, 0.25, 0.5, and 0.75 as possible values, he's giving a nice simple example of how nextFloat() actually works, but he's using N=4 rather than N=2^24.

Alternately, if you really want to access as many possible float values as possible, you could try this instead:

I believe this will also handle returning 1 as a possibility, reasonably well.  The nextDouble() method also returns a subset of possible double values, this time multiples of 2^53.  There will be enough of those that round to 1.  However, you will find that all values are not equally possible here - because, as noted above, the distribution of float values is not uniform.  But the overall distribution is "uniform" in the sense that, for example, you will find approximately equal distributions of values in [0,0.001] and for [0.500,0.501] and [0.999,1].  That is, if you look at the average distribution in each area, it's equivalent.  It's just that possible values are sparser near 1 than they are near 0, so the possibility of a specific exact value like 1 will be much higher than the possibility of 0.

My original code should do basically the same thing, if you set N=1<<53.
 
Tan Quang
Ranch Hand
Posts: 281
jQuery MySQL Database PHP
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:Yeah, true.  Also, there can indeed be real-world cases where you want the max value to occasionally appear, and people will notice and complain if that doesn't happen.  But it really only would happen in cases where the outputs are sufficiently limited to a set of discrete values, enough so that 1/(N+1) is significantly different from 0.  But in such cases, it's probably better to use nextInt() or nextLong() to control exactly what the values will be.

By the way, here's another version - similar idea, with a different value set (that may or may not matter):


I have a question, why N is long? What is the difference if changed to int? I tried to change it to int, it still had the result in [0, 1], it seemed no difference?!
 
Mike Simmons
Master Rancher
Posts: 4457
60
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yeah, that's just left over from the code for other methods.  N can certainly be int in that code.  Also, most of the other uses of long in my code can probably be int, including nextInt() rather than nextLong() - as long as you don't choose an N which is too big for int.  I was experimenting with different values of N and using doubles for comparison, and I left those types in there.
 
Tan Quang
Ranch Hand
Posts: 281
jQuery MySQL Database PHP
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:Yeah, that's just left over from the code for other methods.  N can certainly be int in that code.  Also, most of the other uses of long in my code can probably be int, including nextInt() rather than nextLong() - as long as you don't choose an N which is too big for int.  I was experimenting with different values of N and using doubles for comparison, and I left those types in there.


Yes, N is usually not large (maximum of 100). But I have a question:

So, should I use their final value directly instead of calculating expressions? Like this:

Does it have any harm other than a lack of aesthetics?
 
Campbell Ritchie
Marshal
Posts: 77957
373
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tan Quang wrote:. . . // I usually don't write .0 . . .

I think that is poor style; most people do use .0 and use of thesuffix is likely to reduce the legibility of your code. You still need thesuffix for floats, but I only use floats if some other code forces me to.
Don't use tags inside code tags; they don't work. Don't write such long comments inside code tags; they have harmed the legibility of the whole of this thread.


return (float)(RAND.nextFloat() * CORRECTION_RATIO); // OR: RAND.nextFloat() * 1.0000000596046448
. . .
Does it have any harm other than a lack of aesthetics?

You realise that 1.0000000596046448 contains 17 significant figures in decimal and is far beyond the precision of double arithmetic; had you declared it as a float, it would have degenerated to the equivalent of 1.00000001f. The imprecision inherent in floating‑point arithmetic means you won't get an even distribution of outputs by multiplying. I think you should have stuck with Piet's suggestion with Math#nextAfter().
 
Tan Quang
Ranch Hand
Posts: 281
jQuery MySQL Database PHP
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
So with "N":

Should I leave it in the form of expression (1) or the final result (2)? In the form of the expression, it will look shorter but sometimes more difficult to understand.
Or should I put it in "CORRECTION_RATIO" and don't use "N" anymore?

Or:
 
Campbell Ritchie
Marshal
Posts: 77957
373
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tan Quang wrote:. . . Should I leave it in the form of expression (1) or the final result (2)? . . .

No. Neither nor. You should use Piet's suggestion.

Please don't quote the whole of the preceding post; that adds nothing and is liable to summary removal.
 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic