0

I am generating a random number between a range but I want the number to not be 0. It can be 0.1, 0.2...etc but not 0. How do I do this?

public float selectedValue;

void Start()
 {
    selectedValue = Random.Range(-0.5f, 0.5f);
 }
Vika
  • 419
  • 1
  • 13
  • `if (selectedValue == 0) { Start(); return; }`? – SimonC Sep 01 '22 at 11:07
  • 1
    you could constrain it to a positive number range like 0.1 - 0.5 and multiply it by randomly selected -1 or 1 – Psi Sep 01 '22 at 11:09
  • This answer might help you too: https://stackoverflow.com/questions/18484577/how-to-get-a-random-number-from-a-range-excluding-some-values – Helio Sep 01 '22 at 11:14
  • 2
    The chances of it being exactly zero are very small so just repeating the calculation if it is would be the simplest option. Do it in a loop and it will almost never do more than one iteration and probably never more than two. – user18387401 Sep 01 '22 at 11:14
  • You could check if the number is zero and, if it is, flip a coin and either add or subtract `Mathf.epsilon` to make it not zero. Then it's guaranteed to not loop. – Chuck Sep 01 '22 at 12:20
  • Add 0.1 to the value and knock 0.1 off the other end? – BugFinder Sep 01 '22 at 12:21
  • @BugFinder and if the rng spits out a -0.1? you add 0.1 and get… 0. that’s exactly what is to be avoided here – Psi Sep 02 '22 at 07:55
  • @psi i missed the negative id stick to 0-whatever -0.1 and random then whether it’s negative or positive that way you only pick twice not potential end in a loop – BugFinder Sep 02 '22 at 08:22

5 Answers5

3

Keep finding random values until its value is not zero

float RandomNumExceptZero (float min, float max){
  float randomNum = 0.0f;
    do {
        randomNum = Random.Range (min, max);
    } while (randomNum == 0.0f );
    return randomNum ;
}
Milad Qasemi
  • 3,011
  • 3
  • 13
  • 17
  • This won't compile, since `randomNum` is defined in the do-while-scope. Declare the variable above `do` and it will work just fine. – Max Play Sep 01 '22 at 12:25
  • 2
    I'm a bit iffy on the use of loops for random number generation. I'm waiting for the day when the universe decides to give you zeros for 10 hours. – Voidsay Sep 01 '22 at 13:11
  • why dislike do while loop? I think its better than while loop from my opinion. – Vika Sep 02 '22 at 08:24
  • a loop is generally not the best idea because, in the worst case, it could potentially run forever, if the rng for some reasons decides to deliver only 0 for the rest of the time. this is practically close to impossible, but theoretically the worst case – Psi Sep 02 '22 at 10:28
  • As the other answer said the probability of getting zero is 0.000000047305 and the probability of getting two consecutive zeroes is 0.0000000000000022 and you guys are worried about being stuck in the loop! It will never even has to loop once in practice so you guys have nothing to worry about. – Milad Qasemi Sep 02 '22 at 11:26
  • As I said, it’s very unlikely, but not impossible (statistically speaking). The best solution is always one with a predictable runtime. Even if it hits only 3 zeroes in a row, the fixed O(1) approach is the faster one and especially the more consistent one in terms of actual runtime – Psi Sep 02 '22 at 18:32
2

Building on the suggestion of @Psi you could do this:

public float selectedValue;
void Start()
{
    selectedValue = Random.Range(float.MinValue, 0.5f)*(Random.value > 0.5f?1:-1);
}
Voidsay
  • 1,462
  • 2
  • 3
  • 15
1

Random.Range() takes in 2 arguments in which the second argument is exclusive. You can use it for your advantage by excluding the value 0. The logic used is to find a random value between -0.5f and 0 (exclusive). Use another randomizer to get either a positive value or a negative value

public float selectedValue;

void Start()
{
    selectedValue = Random.Range(-0.5f, 0);
    int sign = Random.Range(0, 2);

    // the value sign can be either 0 or 1
    // if the sign is positive, invert the sign of selectedValue
    if(sign) selectedValue = -selectedValue;
}
Geeky Quentin
  • 2,469
  • 2
  • 7
  • 28
1

I just want to point out that there are 2,113,929,216 (*) float values in the interval [-0.5, 0.5) which gives a ≈ 0.000000047305 % chance that exactly 0.0f will be generated.


(*) found by brute force with C++ std::next_after but both implementation should follow IEEE 754 so I don't expect to be language differences in this regard, unless Unity somehow doesn't use subnormal numbers.

bolov
  • 72,283
  • 15
  • 145
  • 224
0

Well, just make if{} in Update() to pick another random number with same function if it is 0.0f. No way it will get 0.0f two times in a row

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Nov 12 '22 at 10:35