New FastMath method, randomBoundFloat

I noticed that there was no method that randomly generated a float within a user-provided min-max range (or at least, I couldn’t google one up), so I wrote one.

[java]

private float randomBoundFloat(float min, float max)

{

float rand = 0;



do {

// Would this FastMath call be removed, since it’s intended to be called from the FastMath class?

rand = FastMath.nextRandomFloat();

} while (rand < min || rand > max);



return rand;

}

[/java]

Good enough to commit? This is my first contribution to an open-source project and the Commit Practices wiki page is missing, so I don’t know how to proceed from here.

Uhhhh, a loop based on random expression…

[java]

private float randomBoundFloat(float min, float max){

float rand=0;

rand=(FastMath.nextRandomFloat()%(max-min))+min;

return (rand)

}

[/java]



should do the same

First of all it needs to be public static not private. Patches are better as they can be directly applied, and you can also test the functionality of your method directly in the class itself. Follow these guidelines as it will set you up a project from the svn https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:build_jme3_sources_with_netbeans where you can test it.



I’ll let others decide whether it’s “worthy” or not :stuck_out_tongue:

@zzuegg said:
Uhhhh, a loop based on random expression...
[java]
private float randomBoundFloat(float min, float max){
float rand=0;
rand=(FastMath.nextRandomFloat()%(max-min))+min;
return (rand)
}
[/java]

should do the same

I like yours better. :)

Yikes. Erm no, unfortunately that method isn’t usable. The loop could go around a LOT of times.



you need something like:



[java]

private float nextRandomFloat(float min, float max) {

return min+(max-min)*nextRandomFloat();

}

[/java]

1 Like
@zzuegg said:
Uhhhh, a loop based on random expression...
[java]
private float randomBoundFloat(float min, float max){
float rand=0;
rand=(FastMath.nextRandomFloat()%(max-min))+min;
return (rand)
}
[/java]

should do the same


That one doesn't work either. nextRandomFloat() produces a number from 0 to 1. even if it produced one in the range -infinity to +infinity then you would run into problems with the fact that java % is a remainder operator not a true modulus one.

See the alternative implementation I just posted :)
@zarch said:
That one doesn't work either. nextRandomFloat() produces a number from 0 to 1. even if it produced one in the range -infinity to +infinity then you would run into problems with the fact that java % is a remainder operator not a true modulus one.

See the alternative implementation I just posted :)


well, since nextRandomFloat() already produces numbers between 0 and 1 the result of randomBoundFloat should also to be expected between 0 and 1 and the bound set.

In java the % can be used because it is a remainder, afaik modulo '%' cant be used with non integer values....

With your implementation what would be the results of nextRandomFloat(1f, 10f) and nextRandomFloat(-4f, -2f)

//sort min, max here so that min <= max, or throw exepction

rand=(FastMath.nextRandomFloat()+min)*max-min;



Shouldnt this work ?

Yeah, zarch’s version works for all kinds of ranges. It’s the nicest of all of them.



I’m not sure it’s worth another method, though. The math is so trivial.

@zarch said:
With your implementation what would be the results of nextRandomFloat(1f, 10f) and nextRandomFloat(-4f, -2f)


You are right, the result of nRF(1f,10f)=[1f,2f[ and nRF(-4f, -2f)=[-4f,-3f[
I was expecting valid [0,1] inputs. In case of wrong inputs an exception could be thrown :P InputOutOfRangeException input must be between 0 and 1

Here’s the one I use:



[java]

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

final float range = max - min;



return (FastMath.nextRandomFloat() * range) + min;

}

[/java]

I would agree with you @pspeed except that out of 4 solutions on this thread only one actually works for all cases :smiley:



@empire_phoenix. You are adding min in the wrong place. Just work out in your head what the result is if you do min 3, max 4 and nextRandomFlat returns 0. No need to sort min and max either (at least in my implementation). The signs will cancel each other out.

Ooo, ninjad by @madjack with a method mathematically identical to mine o/. Ok, 3 out of 5 incorrect :slight_smile:

@zzuegg said:
You are right, the result of nRF(1f,10f)=[1f,2f[ and nRF(-4f, -2f)=[-4f,-3f[
I was expecting valid [0,1] inputs. In case of wrong inputs an exception could be thrown :P InputOutOfRangeException input must be between 0 and 1


Yep. That sort of assumption can be very dangerous when writing a library though. The better solution is to support any arbitrary float range... :D
@zarch said:
Ooo, ninjad by @madjack with a method mathematically identical to mine o/. Ok, 3 out of 5 incorrect :)


I'll be honest. My first iteration of this was... pretty damn ugly. >_< I tweaked it then verified its integrity with what I found on the internet. The current incarnation comes from a well-known source, but it's almost identical to what I had. ;)
@zarch said:
Yep. That sort of assumption can be very dangerous when writing a library though. The better solution is to support any arbitrary float range... :D


Especially since that would match nextInt() that also takes a range.

Also, you can do:

FastMath.interpolateLinear( FastMath.nextFloat(), min, max);

...no thinking required. :)

Though that does extra work to check the inputs which isn't needed in this case... and the math is different:
return ((1f - scale) * startValue) + (scale * endValue);

...which is like a glsl mix() and I guess is the same thing.
1 Like

Hmm

x=randomFloat, i=min, a=max



((1-x)i) + (xa) = i + x(a-i)

1i-xi+xa =

i+x(-i+a) =

i+x(a-i)



The two are mathematically identical, although the i+x(a-i) does two additions and a multiply and the other one does two additions and two multiplications.

@zarch said:
Hmm
x=randomFloat, i=min, a=max

((1-x)i) + (xa) = i + x(a-i)
1i-xi+xa =
i+x(-i+a) =
i+x(a-i)

The two are mathematically identical, although the i+x(a-i) does two additions and a multiply and the other one does two additions and two multiplications.


Also, I believe i + x(a-i) accumulates less floating point error.

If anyone wants to use this, the right code is this (nextFloat() doesn’t exist):



[java]

FastMath.interpolateLinear( FastMath.nextRandomFloat(), min, max);

[/java]

1 Like