B4J Question A stupid question to end the year.... How to generate a small number, positive or negative randomly.

Mark Read

Well-Known Member
Licensed User
Longtime User
Yesterday whilst working on a project I needed to generate randomly a -1 or a 1. I tried for some time to get it working and thought how stupid can I be. Finally I came up with this:
B4X:
Dim RandomValue As Int=Rnd(1, 3)*-1
This was then to be used in the following line:
B4X:
If (center<>s) And (center<>e) Then boltarray(center)=(boltarray(e)+boltarray(s))/2  + Rnd(0,1)*actlevel*RandomValue
The result of the last part is a positive or negative number between 0 and 1.
Then it hit me, while writing this, why don't you combine the two (not tested):
B4X:
If (center<>s) And (center<>e) Then boltarray(center)=(boltarray(e)+boltarray(s))/2  + Rnd(-1,1)*actlevel

Just as info. The application is to move the end point of a line by a small amount based on its length.

And my question: How to prevent 0?
 

Mark Read

Well-Known Member
Licensed User
Longtime User
Both of the above are good answers but I actually need a value between -1 and 1 but not 0.
Maybe this will do the job (not tested):
B4X:
Sub RandomValue As Double
    Return IIf(Rnd(0, 2) < 1, Rnd(0, 1), -Rnd(0, 1))
End Sub

Edit: have just seen that this will not work as RND produces an integer
 
Last edited:
Upvote 0

aeric

Expert
Licensed User
Longtime User
Both of the above are good answers but I actually need a value between -1 and 1 but not 0.
Maybe this will do the job (not tested):
B4X:
Sub RandomValue As Double
    Return IIf(Rnd(0, 2) < 1, Rnd(0, 1), -Rnd(0, 1))
End Sub
You should have mentioned that you want the value in Double.
Check the following thread:
 
Upvote 0

Mark Read

Well-Known Member
Licensed User
Longtime User
You should have mentioned that you want the value in Double.
Sorry if I did not make myself clear. In my post I wrote "The result of the last part is a positive or negative number between 0 and 1." and the question how to stop 0.

Being able to describe the problem is half the solution!
 
Upvote 0

emexes

Expert
Licensed User
How many decimal places would you like the number to be?

Like, even if it's Double, it's still not continuous, it's discrete steps between each fractional value and the next.

Also, between -1 and 1: is that including -1.00000000 and +1.000000000, or excluding?
 
Last edited:
Upvote 0

emexes

Expert
Licensed User
Let's say six decimal places, not including -1, 0 and 1, eg -0.999999 to -0.000001 and 0.000001 to 0.999999, I'd use:

B4X:
Dim RandomInt As Int = Rnd(-999999, 999999)    'returns -999999 to 999998 ie missing 999999
If RandomInt = 0 Then RandomInt = 999999    'move/append numero non grata 0 to be the missing 999999
Return RandomInt / 1000000

or a simpler way to not include particular values is:

B4X:
Do While True
    Dim RandomInt As Int = Rnd(-999999, 999999 + 1)    '-999999 to 999999 inclusive
    If RandomInt <> 0 Then Exit
Loop
Return RandomInt / 1000000
 
Last edited:
Upvote 0

emexes

Expert
Licensed User
Hmm... because the number is split into two equivalent ranges mirrored about 0, you could use:

B4X:
Dim RandomInt As Int = Rnd(1, 1000000)    '1 to 999999
If Rnd(-1, 1) = 0 Then RandomInt = -RandomInt    'or <> 0, both work 🤫 
Return RandomInt / 1000000

or if you prefer brevity above clarity, maybe even:

B4X:
Return Rnd(1, 1000000) * (Rnd(0, 2) * 2 - 1) / 1000000
 
Upvote 0

Mark Read

Well-Known Member
Licensed User
Longtime User
@emexes : Thanks for your time and trouble. I have tried a few things and will stick with:

B4X:
Sub RandomValue As Double
    Return Rnd(-10000,10000)/10000
End Sub

as it is simple and works well enough. The chance of getting 0 is very small I think. I did say in the title, it was a stupid question!
 
Upvote 0

aeric

Expert
Licensed User
Longtime User
@emexes : Thanks for your time and trouble. I have tried a few things and will stick with:

B4X:
Sub RandomValue As Double
    Return Rnd(-10000,10000)/10000
End Sub

as it is simple and works well enough. The chance of getting 0 is very small I think. I did say in the title, it was a stupid question!
Your code above will not return 1. The second parameter for Rnd is exclusive.

My proposed mod:
B4X:
Sub RandomValue As Double
    Dim value As Double = Rnd(-10000, 10001) / 10000
    If value = 0 Then Return RandomValue
    Return value
End Sub
 
Upvote 0

Mark Read

Well-Known Member
Licensed User
Longtime User
It seems that things are getting confused now. I don't want 1 or -1 really. I need a number between -1 and 1 but not 0.

It all started with this line:
B4X:
If (center<>s) And (center<>e) Then boltarray(center)=(boltarray(e)+boltarray(s))/2  + Rnd(0,1)*actlevel*RandomValue
where the last part after the "+" sign generates a -1<x<1 but not 0. RandomValue should be 1 or -1.

I know how to use the Rnd function but forgot that it produces an integer, which caused the code to do strange things.

Your mod would make sure no 0 is used but I would still use 10000.

Thanks
 
Upvote 0

MicroDrie

Well-Known Member
Licensed User
Longtime User
It seems that things are getting confused now. I don't want 1 or -1 really. I need a number between -1 and 1 but not 0.

After reading all the posts, what if you generate a random number between 1 and 999 and divide that result by 1000 (excluding -1 and 1) and then randomly multiply by 0 or -1 again to exclude the value 0?

Generate random numbers between -1 and 1 without the value 0:
Sub GenerateRandomDouble() As Double
 ' Exclude both 0 and 1
    Dim r As Double = Rnd(1,1000)/1000
  ' take random 100 cases
    Dim m As Int = Rnd(0,100)        
' 50/50 positive / negative
    If m >49 Then r = r * -1                   
    Return r
End Sub

Update 1: Change value line 7 from 50 to 49 for 50/50 distribution and added comment
update 2: Change value line 3 from 999 to 1000 to include 999
 
Last edited:
Upvote 0

emexes

Expert
Licensed User
I need a number between -1 and 1 but not 0.

Are you looking to do a coin flip where one side is 1 and the other side is -1?

Or are you looking to get back a number ranging from -1 to 1 but not including 0?

Interestingly, on a truly continuous number scale, the probability of getting a 0 is theoretically 0. But Doubles are discrete, so... it could happen.

But what is wrong with 0 anyway? It looks like you're adding some random jitter, and 0 would seem as likely as any other offset.
 
Upvote 0

emexes

Expert
Licensed User
How about 🤣 :

B4X:
Return Array As Byte(-1, 1)(Rnd(0, 2))

or, more generally:

B4X:
Dim DesirableRandomValue() As Double = Array As Double(-1, 1)

Return DesirableRandomValue(Rnd(0, DesirableRandomValue.Length))
 
Upvote 0

emexes

Expert
Licensed User
Maybe this will do the job (not tested):
B4X:
Sub RandomValue As Double
Return IIf(Rnd(0, 2) < 1, Rnd(0, 1), -Rnd(0, 1))
End Sub

This would do what you were aiming for there:

Return IIf(Rnd(0, 2) < 1, 1, -1)

Or are you also looking for values other than only just -1 and 1 ? In which case, use this,

B4X:
Return Rnd(1, 1000000 + 1) * (Rnd(0, 2) * 2 - 1) / 1000000

if you want to include -1.000000 and 1.000000 as candidates, or if not, then:

B4X:
Return Rnd(1, 1000000) * (Rnd(0, 2) * 2 - 1) / 1000000
 
Upvote 0
Top