# Just curious about this Rnd(Rnd(Rnd*200)) result... • ### คำถาม

• It seems to me that the following stmt
r=rnd*(rnd*(rnd*200))
ought to return a value over 199 occasionally (about 1 in 8 million times or so).  However, I've run this stmt in the following program, and in over 25,600,000,000 tries it has never reported a value over 199.   (However, 198 occurs regularly.)

What am I missing here?

option explicit off
Module mainModule
Sub Main()
randomize()

for y=1 to 1000000
for x = 1 to 8000000 : R=rnd*(rnd*(rnd*200))
if r>199 then console.writeline("  ! 199 !  ") '  Report if value is over 199
next x
console.write(Cstr(y)+" ") ' Report every 8 million tries
next y

End Sub
End Module

[Visual Basic 2008    vista SP1]

6 มกราคม 2554 13:50

### คำตอบ

• Until this thread, although I didn't use it, I thought that Rnd() was just as good as Random().  It isn't.  The following code repeats every 17,000,000 tests.  Making the commented changes to use Random(), I haven't found a repeat.

Module Module1

Sub Main()
Console.WriteLine(
"Running Test")

Dim TestNo As Long
'Dim Rnd as new Random
Do
TestNo += 1

Dim Result As Double = Rnd() * 200  'Rnd.NextDouble
If Result > 199 Then
Dim Result2 As Double = Rnd() * 200 'Rnd.NextDouble
If Result2 > 199 Then
Dim result3 As Double = Rnd() * 200 'Rnd.NextDouble
If result3 > 199 Then
Console.WriteLine(TestNo.ToString + " " + Result.ToString + " " + Result2.ToString + " " + result3.ToString)
TestNo = 0

End If
End If
End If
Loop
End Sub
End
Module

• ทำเครื่องหมายเป็นคำตอบโดย 7 มกราคม 2554 20:49
• แก้ไขโดย 7 มกราคม 2554 20:54
7 มกราคม 2554 20:45

### ตอบทั้งหมด

• The largest rnd ever returns is 0.9999999
which happens every 1 to 6 million times or so

0.9999999 cubed is 0.9999997

0.9999997 times 200 is 199.99994

The largest value that  rnd*(rnd*(rnd*200))  ever returns is 198.3898

Why?

6 มกราคม 2554 14:29
• You're assuming that the value returned by three consecutive invocations of rnd could be 0.9999999 each time. Perhaps a bit unlikely...

Do use actually want to call rnd once and cube that?

--
Andrew

6 มกราคม 2554 14:50
• If you want more predictable randoms use the .NET Random.
6 มกราคม 2554 15:13
• Three .9999999s in a row aren't necessary; just close to it:

If there were three values of 0.9983308 or greater in a row,
the result of them cubed (0.9950007+) times 200 would be 199.0001+
but it never happens in this program.

In billions of iterations, the result was always a max of 198.3898

I don't need this resolved, I'm just curious what's going on.

RE. JohnWein's suggestion:
I don't know .NET  -  I barely know visual Basic!
I've used gwBasic my whole life - which vista 64bit won't run.

7 มกราคม 2554 16:24
• Your rnds aren't independent.  As you've seen it's not possible for the pseudorandom rnd to generate the same number 3 times in succession.  If you used 3 .NET Randoms and ensured that they were seeded from widely different seeds, you might get the result you're looking for.
7 มกราคม 2554 16:46
• I would also add that you possibly don't fully understand how 'random' (and probability) really works.

I would ask why do you think it should return a value of X in Y iterations?

Or asking another way, how many iterations would you need to have a 100% chance of getting the result you want at least once? How about a 95% chance of getting the result you want?

What would you say if I got it on the first try?

As a follow up, try thinking about probabilities from the position of NOT getting the result you want: that is, if there's a 1% chance of a given result, each time you try there's a 99% chance of NOT getting that result. In addition, each result is not dependent on the last result. If you rolled 6 dice in a row and each one rolled a 6, what is the chance of rolling another 6?

(This is all aside from the fact that there's a difference between a random result and a computer generated pseudo-random result).

Stephen J Whiteley
7 มกราคม 2554 18:32
• Try this:

Module Module1

Sub Main()

Dim Rnd(2) As Random
Rnd(0) =
New Random
Console.WriteLine(
"Enter to seed Rnd(1)")
Rnd(1) =
New Random
Console.WriteLine(
"Enter to seed Rnd(2)")
Rnd(2) =
New Random
Console.WriteLine(
"Running Test")

Dim TestNo As Long
Do
TestNo += 1

Dim Result As Double = Rnd(2).NextDouble * Rnd(1).NextDouble * Rnd(0).NextDouble * 200

If Result > 199 Then
Console.WriteLine(TestNo.ToString + " " + Result.ToString)
Console.WriteLine(
"Enter Q to quit.")

If Console.ReadLine = "Q" Then Exit Do
End If
Loop
End Sub
End
Module
Module
Module1

Sub Main()

Dim Rnd(2) As Random
Rnd(0) =
New Random
Console.WriteLine(
"Enter to seed Rnd(1)")
Rnd(1) =
New Random
Console.WriteLine(
"Enter to seed Rnd(2)")
Rnd(2) =
New Random
Console.WriteLine(
"Running Test")

Dim TestNo As Long
Do
TestNo += 1

Dim Result As Double = Rnd(2).NextDouble * Rnd(1).NextDouble * Rnd(0).NextDouble * 200

If Result > 199 Then
Console.WriteLine(TestNo.ToString + " " + Result.ToString)
Console.WriteLine(
"Enter Q to quit.")

If Console.ReadLine = "Q" Then Exit Do
End If
Loop
End Sub
End
Module

7 มกราคม 2554 19:27
• I'm sure I have a good understanding of probabilities.  I also understand that the Rnd function in vBasic is a simulation of a random number, and is not random at all after the seed is established.

I do not know the algorithm, however, and I realize the algorithm may be the answer.
I was just thinking someone knew more about the algorithm or whatever is causing this limitation.

To answer your question, I would NEVER have a 100% chance of getting the result I'm looking for.
But if I have a 99.9999999% chance of getting said result, and I don't...   I consider that conclusive.

7 มกราคม 2554 19:37
• I'm sure I have a good understanding of probabilities.  I also understand that the Rnd function in vBasic is a simulation of a random number, and is not random at all after the seed is established.

I do not know the algorithm, however, and I realize the algorithm may be the answer.
I was just thinking someone knew more about the algorithm or whatever is causing this limitation.

From the help for Random,

"The current implementation of the Random class is based on Donald E. Knuth's subtractive random number generator algorithm. For more information, see D. E. Knuth. "The Art of Computer Programming, volume 2: Seminumerical Algorithms". Addison-Wesley, Reading, MA, second edition, 1981."

Edit: But that's for the .NET random, I couldn't quickly find a reference to how the VB random function works.

--
Andrew

• แก้ไขโดย 7 มกราคม 2554 19:51 Looked at wrong version of random.
7 มกราคม 2554 19:42
• Thank you, John  —  I will try that.  I'm very short on sleep at the moment, and there are a couple things in your program I'm not familiar with, but I will learn them.

7 มกราคม 2554 19:43
• I do not know the algorithm, however, and I realize the algorithm may be the answer.
I was just thinking someone knew more about the algorithm or whatever is causing this limitation.
You don't need to know the algorithm to know the limitation.  A pseudorandom number generator generates a finite predetermined sequence of numbers dependent upon the seed.  You're using 3 sequential numbers in that sequence.  Although each number generated by the generator obeys general criteria for randomess, sequential numbers are not random at all.  They are, in fact, deterministic.
7 มกราคม 2554 19:56
• Until this thread, although I didn't use it, I thought that Rnd() was just as good as Random().  It isn't.  The following code repeats every 17,000,000 tests.  Making the commented changes to use Random(), I haven't found a repeat.

Module Module1

Sub Main()
Console.WriteLine(
"Running Test")

Dim TestNo As Long
'Dim Rnd as new Random
Do
TestNo += 1

Dim Result As Double = Rnd() * 200  'Rnd.NextDouble
If Result > 199 Then
Dim Result2 As Double = Rnd() * 200 'Rnd.NextDouble
If Result2 > 199 Then
Dim result3 As Double = Rnd() * 200 'Rnd.NextDouble
If result3 > 199 Then
Console.WriteLine(TestNo.ToString + " " + Result.ToString + " " + Result2.ToString + " " + result3.ToString)
TestNo = 0

End If
End If
End If
Loop
End Sub
End
Module

• ทำเครื่องหมายเป็นคำตอบโดย 7 มกราคม 2554 20:49
• แก้ไขโดย 7 มกราคม 2554 20:54
7 มกราคม 2554 20:45
• Thanks so much, John.  Your programs will keep me occupied for a while!
7 มกราคม 2554 20:53
• For those who may be interested, Rnd() repeats its sequence (for a given seed) every 16777216 calls.

So this code
randomize(1234)
do
for x as single = 1 to 16777215 : rnd : next
console.writeline(rnd.tostring)
loop
will write the same number over and over.

More useless information...
If you use rnd and then later want to get the same results you would've gotten if you had not used rnd, you gotta call rnd exactly as many times as will bring the total of rnd calls (so far) to 16777216 times - then randomize(seed) and continue as usual.
If the two sequences you seek use the same seed, you do not need to repeat the randomize() cmd.

Alternatively...
If your pgrm is such that you may or may not have called rnd earlier, and you want to get the same results you would've gotten before you called rnd, you can use this code:
z=rnd(-1)  :  randomize(seed)  :  for x=1 to 12827730  :  z=rnd  :  next
'  Vb.net/net 2.0 should be re-initialized for rnd use     (z, x are type single)

But don't use rnd() for security/encryption purposes!

Use md5.computeHash(string) or Random.NextDouble or CryptoStream() or anything but Rnd()!

• แก้ไขโดย 27 พฤศจิกายน 2563 4:21 Typos!
27 พฤศจิกายน 2563 4:04