Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

random number generator

MrDEB

Well-Known Member
I downloaded the random number generator that is supposed to generate nmbers from 1 - 5 but it doesn't do what it is supposed to

here is the code including the "rand" module


Device = 18F43K22
Clock = 16

// int osc and IO pin libraries
Include "intosc.bas"
#option DIGITALIO_INIT = true // automatically call setalldigital
Include "setdigitalio.bas"

// lcd
#option LCD_DATA = PORTD.4
#option LCD_RS = PORTD.2
#option LCD_EN = PORTD.3
Include "LCD.bas"
Include "convert.bas"

//Include "RNDByte.bas"
Include "Rand.bas"
Include "convert.bas"
Dim Y As Byte



TRISB=0

InitializeRND(4)'if desired

main:
Y=GetRND()
PORTB = (Y)

WriteAt(1,1,DecToStr(Y)," ")
DelayMS(2000)
Cls
GoTo main


{
RandGen Module
This is the Module code For the above example. Just copy And paste into the Swordfish IDE And Save in you UserLibrary folder As "RNDByte.bas"...

{
*****************************************************************************
* Name : RndByte.BAS *
* Author : David Eather *
* Notice : This code is placed into the Public Domain *
* : *
* Date : 19/07/2011 *
* Version : 1.0 *
* Notes : call InitializeRND(pValue) with a value between 0-255 *
* : call GetRND() to get a Byte 0 to 255 *
*****************************************************************************
}

{
Module Rand

Dim LCG,GLFSR As Byte

Public Function GetRND() As Byte
'LCG
LCG=(7*LCG+17)

'Galios LFSR
If (GLFSR And 1) = 1 Then
GLFSR = GLFSR Xor 135 '135 is the tap
GLFSR = (GLFSR >> 1) Or $80
Else
GLFSR = (GLFSR >> 1)
End If
result = GLFSR Xor LCG
End Function

Public Sub InitializeRND(ByVal ReSeed As Byte)
LCG = ReSeed
GLFSR = LCG Xor $55 'just making the start values very different - not realy important
If GLFSR = 0 Then 'except that GLFSR must not be zero
GLFSR=1
EndIf
End Sub

GLFSR=1
LCG=84
End
 
For MrDEB's situation (if I have guessed right), when a new game is to be started, a button will be pressed to start. When that button is pressed, the timer value (which is changing very rapidly and is not presented to the players) is read, the modulo is calculated and the first play is indicated.
 
You can add, subtract, multiply, and delete to change range without affecting the remaining numbers. Modulo is different. Consider the extreme: i.e., %1 converts every value to 0. I am not suggesting anyone do that, but you can do the other operations with immunity with 1. %2 will also give 50% 0's. At some point modulo doesn't cause a big problem. I manually did a 4-bit binary test and %C causes the same bias as %8 did with decimal. %5 seems safe.

My point is that modulo can bias the result. The fact that effect can be minimized in certain cases doesn't' make it any better compared to safe alternatives, like deletion.

Sorry, but you seem to be entirely wrong, on all counts?.

Modulo is just dividing, but returns the remainder, which is exactly what want for scaling random numbers.

Deletion is a crazy idea - and will massively skew the results, as the vast majority are thrown away.
 
That's basically why I called rand in the switch pressed (or not) loop,
If switch pressed then
,do switch pressed stuff
Else
call rand(any number)
Endif

It just makes the rand function dependant on human timing.

Mike.
 
Sorry, but you seem to be entirely wrong, on all counts?.

Modulo is just dividing, but returns the remainder, which is exactly what want for scaling random numbers.

Deletion is a crazy idea - and will massively skew the results, as the vast majority are thrown away.
I hope you understood that by deletion, I meant only values outside the range, which I thought was obvious. I also meant in a practical sense not erasing per se, but simply skipping. If you think that skews the relative distribution of the remaining numbers, assuming they were random initially, you are hopelessly wrong. That was and is standard practice in using "random number tables." Or as others on this thead have said, if your program returns a number out of range, just go to the next number or re-run the program until you get one in range. It is easy to demonstrate how modulo skews the results. You seem to ignore.that.

In the past, ETO tended to ban or thread-ban individuals who disagreed with a moderator. That won't be necessary. This is my last post in this thread.
 
I hope you understood that by deletion, I meant only values outside the range, which I thought was obvious. I also meant in a practical sense not erasing per se, but simply skipping. If you think that skews the relative distribution of the remaining numbers, assuming they were random initially, you are hopelessly wrong. That was and is standard practice in using "random number tables." Or as others on this thead have said, if your program returns a number out of range, just go to the next number or re-run the program until you get one in range. It is easy to demonstrate how modulo skews the results. You seem to ignore.that.

Well you seem to misuse modulo in order to try and make it look bad - using it properly is perfectly fine.

As the minimum range of rand() is 32K, and if you wanted to generate a random YES or NO (Heads or Tails?), then modulo would return 0 for numbers less than 16K and 1 for numbers greater than 16K - so 50% chance of each, and exactly what you want.

Repeatedly running rand() until you get a result of 0 or 1, and deleting all others, could very well take a long time.

In the past, ETO tended to ban or thread-ban individuals who disagreed with a moderator. That won't be necessary. This is my last post in this thread.

Not at all, any bans have been for abusive posts - something that doesn't apply to you - constructive discussion is always welcome.
 
OK, I've been doing a little work - and checking the actual results from the modulus scaling code I posted, just looping through with all possible values (rather than random ones).

Here's the code - I had to drop the maximum rand() value from 32767 to 16763, as otherwise the on-line compiler I used failed https://www.w3schools.com/c/tryc.php?filename=demo_helloworld

Feel free to cut and paste and have a play.

C:
#include <stdio.h>


#define lower 1
#define upper 52
#define max_value 16383

int x, y;
int yy[upper+1];

int main()
{
    
    for(x=0; x<max_value; x++)
    {
          y =  (x % (upper - lower + 1)) + lower;
        yy[y]++;
        printf ("Index value = %d, Scaled value = %d\n", x, y);
    } 
    
    for(x=lower; x<upper+1; x++)
    {

        printf ("Return value = %d, Total numbers of value = %d\n", x, yy[x]);
    }
}

And here's a small part of the output, a count of the number of individual values within the specified range, only showing the first ten, as all the rest are 315. For the full 32767 range the numbers would presumably be 633 and 632. I don't see how that tiny skewing (due to the combination of the max_value and range values) would be an issue, and deleting values would be probably be more of a problem.

C:
Return value = 1, Total numbers of value = 316
Return value = 2, Total numbers of value = 316
Return value = 3, Total numbers of value = 316
Return value = 4, Total numbers of value = 315
Return value = 5, Total numbers of value = 315
Return value = 6, Total numbers of value = 315
Return value = 7, Total numbers of value = 315
Return value = 8, Total numbers of value = 315
Return value = 9, Total numbers of value = 315
Return value = 10, Total numbers of value = 315
 
I played around with my method of generating a random number in a given range in response to a human event like a button press, and came up with this function, which allows specifying the desired random number range. An event like pressing a button causes the value of a free-running 16 bit timer to be read, which is converted to a random number in the desired range by the modulo function.

jpanhalt 's objection to the modulo function causing possible uneven distribution has been addressed by discarding timer values beyond the point where a complete modulo sequence can be completed.

This method is simple to set up and use, with the slight complication that two timer registers must be set up, which will vary depending on the chip used.

The distribution for a few hundred button presses for Range = 6 is shown below.

Code:
  Function RandomPress(Range As Byte) As Byte
        Dim TimerValue1 As Word
        TimerValue1.byte0 = TMR1L          'Read value of Timer1
        TimerValue1.byte1 = TMR1H          
        MaxRange = 65535 - (65535 Mod (Word(65535/range) * range)) 'maximum range for complete sequence
        While timervalue1 > MaxRange                               'timer value too big
            TimerValue1.byte0 = TMR1L                                'so try again
            TimerValue1.byte1 = TMR1H  
        Wend        
        Result = (TimerValue1 Mod Range) + 1
  End Function 

  'Timer setup - see data sheet for register names and settings
  'Timer source is Fosc/4, with prescaler = 8
  'Register names are predefined in chip setup file
  T1CON = %00110011
  T1GCON = %00000000


  'Usage
  'When switch pressed, call RandomPress(Max Number desired):
  'If SwichedPress = true then
  '     RandomNumber = RandomPress(6)
  'End If

RandomPress Result.jpg
 

Latest threads

New Articles From Microcontroller Tips

Back
Top