Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 00:40 30 Mar 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Random number behavior

Author Message
daveculp
Newbie

Joined: 02/07/2020
Location: United States
Posts: 22
Posted: 09:39pm 03 Jul 2020
Copy link to clipboard 
Print this post

Ive been messing around the CMM2 and today I was writing a simple random walker routine.  It works like so:

1. Start in the middle of the screen
2. Generate a random color
3. Generate a random x offset in the range -1,0,1
4. Generate a random y offset in the range -1,0,1
5. Plot the point
6. Pause a bit
7. Go back to 2 and do it all over again

It can make some interesting shapes but I noticed the random number generation didnt seem uniform so I kept track of how many times each number is generated.

It turns out that the middle number (1) is being generated almost twice as much as the other two. Is this due to how MMBasic converts from a float to an int.  Is there a better way to do this?

In reality, the way this implementation  works is it generates a number in the range of 0 to 2 inclusive then subtracts 1 to get the range of -1 to 1 inclusive.


REM ================================================================================
REM RANDOM WALKER
REM ================================================================================
x = MM.HRES/2
y = MM.VRES/2
DIM x_total(2)
DIM y_total(2)
DIM INTEGER step_x, step_y

cls black

do while INKEY$ = ""
 r = rnd * 255
 g = rnd * 255
 b = rnd * 255

 step_x = (rnd*2)
 x_total(step_x) = x_total(step_x) + 1

 step_y = (rnd*2)
 y_total(step_y) = y_total(step_y) + 1
 
 step_x = step_x - 1
 step_y = step_y - 1

 x = x + step_x
 y = y + step_y

 pixel x,y, RGB(r,g,b)
 pause (10)
loop

print "x totals: ";x_total(0), x_total(1), x_total(2)
print "y totals: ";y_total(0), y_total(1), y_total(2)


Edited 2020-07-04 07:44 by daveculp
 
daveculp
Newbie

Joined: 02/07/2020
Location: United States
Posts: 22
Posted: 10:07pm 03 Jul 2020
Copy link to clipboard 
Print this post

The last run resulted in the following totals:

x totals:  2312  4464  2264
y totals:  2182  4546  2312

The numbers represent the number of times 0, 1 and 2 were generated.  One is generated 2X as much as the other numbers.  Im wondering if it has to do with how numbers are converted from floating point types to integers.
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5867
Posted: 10:26pm 03 Jul 2020
Copy link to clipboard 
Print this post

It is safer to control the conversion from float to INT yourself.

step_x = int(rnd*3)

That will give you a very well distributed series of random numbers.

Jim
VK7JH
MMedit   MMBasic Help
 
daveculp
Newbie

Joined: 02/07/2020
Location: United States
Posts: 22
Posted: 10:30pm 03 Jul 2020
Copy link to clipboard 
Print this post

  TassyJim said  It is safer to control the conversion from float to INT yourself.

step_x = int(rnd*3)

That will give you a very well distributed series of random numbers.

Jim


Works beautifully now!  Thanks!
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3641
Posted: 10:39pm 03 Jul 2020
Copy link to clipboard 
Print this post

In the version posted, with
step_x = (rnd*2)
x_total(step_x) = x_total(step_x) + 1

step_x should never be as large as 2 (because rnd is - or should be - always less than 1).

So how is x_total(2) not 0?

What am I missing?

It looks like rnd is broken or else array indexing / the calculation of the index is.

John
Edited 2020-07-04 08:41 by JohnS
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 5867
Posted: 10:53pm 03 Jul 2020
Copy link to clipboard 
Print this post

Going from float to INT uses rounding, not INT

The first methods used could be regarded as 4 bins 0-0.5, 0.5-1.0, 1.0-1.5, 1.5-2.0

The middle two get bundled together.

Jim
VK7JH
MMedit   MMBasic Help
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3163
Posted: 10:54pm 03 Jul 2020
Copy link to clipboard 
Print this post

When assigning a float to an integer MMBasic will round the float to the nearest integer.  RND gives a number between 0 and 0.999999 so step_x = (rnd*2) could be rounded up to 2.

However the INT() function simply discards the fractional portion.  So INT(rnd*2) will never return 2.

EDIT: Jim beat me to it.

Geoff
Edited 2020-07-04 08:55 by Geoffg
Geoff Graham - http://geoffg.net
 
daveculp
Newbie

Joined: 02/07/2020
Location: United States
Posts: 22
Posted: 11:27pm 03 Jul 2020
Copy link to clipboard 
Print this post

  TassyJim said  Going from float to INT uses rounding, not INT

The first methods used could be regarded as 4 bins 0-0.5, 0.5-1.0, 1.0-1.5, 1.5-2.0

The middle two get bundled together.

Jim


Based upon my experimentation I figured that was what was going on, I just wasnt sure how to fix it.  Now I know to convert manually from a FLOAT to INT instead of having it do it automatically.
Edited 2020-07-04 09:31 by daveculp
 
daveculp
Newbie

Joined: 02/07/2020
Location: United States
Posts: 22
Posted: 11:36pm 03 Jul 2020
Copy link to clipboard 
Print this post

This also helped me fix anoyjer issue with a Sierpienski's triangle generation program.  The triangle got generated but it was obviously less filled in in places, which would only happen if there was not an even distribution of random numbers.  Applying this fixed it.
 
panky

Guru

Joined: 02/10/2012
Location: Australia
Posts: 1094
Posted: 01:18am 04 Jul 2020
Copy link to clipboard 
Print this post

  Geoffg said  
...... the INT() function simply discards the fractional portion.  So INT(rnd*2) will never return 2.


Geoff, for negative numbers, does INT not round to the next more negative number? Ie. INT(-2.11) will round to -3 whereas FIX will just delete the fractional component of both positive and negative numbers?

panky
... almost all of the Maximites, the MicromMites, the MM Extremes, the ArmMites, the PicoMite and loving it!
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3163
Posted: 02:35am 04 Jul 2020
Copy link to clipboard 
Print this post

  panky said  Geoff, for negative numbers, does INT not round to the next more negative number? Ie. INT(-2.11) will round to -3 whereas FIX will just delete the fractional component of both positive and negative numbers?


Yes, correct.  You should use FIX() when you want a true integer conversion without any rounding.  But in this case it worked as there were no negative numbers.

It is a bit confusing but blame Bill because that is how he did it in Microsoft BASIC.

Geoff
Geoff Graham - http://geoffg.net
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3641
Posted: 09:57am 04 Jul 2020
Copy link to clipboard 
Print this post

  Geoffg said  When assigning a float to an integer MMBasic will round the float to the nearest integer.

Geoff


Oh!

I don't recall other BASICs doing that.  They do an implied FIX.

John
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3163
Posted: 11:13am 04 Jul 2020
Copy link to clipboard 
Print this post

  JohnS said  Oh!
I don't recall other BASICs doing that.  They do an implied FIX.
John


From the GWBASIC User's Manual:


Geoff Graham - http://geoffg.net
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3641
Posted: 04:48pm 04 Jul 2020
Copy link to clipboard 
Print this post

So I gather.

It's a big surprise to me, as some (many?) others do not do that.  Could make porting programs a bigger challenge than might be expected.

I just checked, and by way of example DEC's BASIC-PLUS truncates.

I wonder what the ANSI standard says.

(I suspect I've never used anything but an integer for an array index, however.)

John
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3163
Posted: 12:16am 05 Jul 2020
Copy link to clipboard 
Print this post

  JohnS said  by way of example DEC's BASIC-PLUS truncates.

MMBasic tries to keep compatibility with Microsoft BASIC.

Annoyingly the ANSI standard does not cover integer types but it does specify that floats must be rounded when indexing arrays (which is an integer conversion).

Geoff
Geoff Graham - http://geoffg.net
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3641
Posted: 01:16pm 05 Jul 2020
Copy link to clipboard 
Print this post

It makes sense to do that.

It also explains why the outer two (indices 0 & 2) of the totals posted roughly sum to the middle one.

John
 
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024