Jump to content

Snickers11001001

Members
  • Posts

    130
  • Joined

  • Last visited

  • Days Won

    5

Community Answers

  1. Snickers11001001's post in Some simple programming related questions was marked as the answer   
    Check out the links provided they really do help.  
    RND takes one of three parameters.   RND(1) [or any positive parameter, generally] generates a random number between  0 and 1 based on the next 'seed' -- an internal number that is behind the maths of this pseudo-random number generator) -- and updates the seed.   RND(0) does the same thing but uses a byte of the internal clock as the seed.    RND with a negative number [i.e., RND(-2.39997)] uses the supplied parameter as, in essence, the seed.    Which means calling it with the same neg. number gives the same random number between 0 and 1. 
    So   A=RND(1) is the basic function.     But to get what you want, you have to do something with that random decimal value it spits out, which again is generated as a number greater than 0 and less than 1.
    If you want an integer (no decimal fraction) number from 0 to 9 then reason it out:    You need to us the INT() function too.     And you take that decimal number between 0 and 1 and multiply it by the highest number you want + 1 (assuming you want the entire range of 0 to the highest number) 
    R=INT(RND(1)*10)   
    will cause the variable 'R' to have a random number from 0 to 9.     (Think about it, even if the RND() function itself returns .99999999 multiplying it by 10  gets you 9.999999 and then taking the INT() function of that returns a 9.
    About the INT() function.   Its not 'rounding' in the sense you might be used to, i.e., in the event the fractional component is greater than .5 it does not 'round up'   
    Instead, INT() is a 'floor' style rounding, which means the output is always LESS than the input.     With a positive number, say INT(9.9999), it returns the next integer that is LESS than the value supplied, which is to say it disregards the decimal fraction, i.e., it returns 9 in this example.   
    But with a negative number, say  INT(-10.999), it ALSO returns the next integer that is LESS than the value supplied, i.e.,   -11 here. 
    All of that is why  INT (RND(1)*10) gives you a value between 0 and 9
    So, if you want it to return two random single digit numbers, let's say you want to put them in variables to use later you need two calls of this function. 
    10  N1=INT(RND(1)*10)
    20  N2=INT(RND(1)*10)
    30  PRINT N1, N2
     
    EDIT: Just read more carefully and saw your thing about wanting either a 1 or 2...   that means you multiply by the DIFFERENCE between the lowest number and highest number you want +1.
    To have a lower boundary you just add it as the base to your calculations, i.e,
    N1 = 1+INT(RND(1)*2)
    N2 = 1+INT(RND(1)*2)
    To test these, try this FOR/NEXT loop from the command line:
    FOR L=1 TO 10: PRINT 1+INT(RND(1)*2):NEXT
    After it prints its sequence of 1s and 2s, scroll your cursor up and hit enter on the same command again and watch the sequence change.  Viola.  Pseudo randoms of either 1 or 2. 
    EDIT:   Geez, I was pretty sloppy in answering this...  so I went in and fixed some typos and added clarity.   Substance is the same, it just reads better. 
  2. Snickers11001001's post in BASIC - Out of Memory was marked as the answer   
    It could be strings heap issues generated by your "GET" function, but as its erroring out in the FOR/NEXT loop I'd say you've got some coding issues that are smashing the BASIC stack. 
    Whenever BASIC does a GOSUB, or starts a FOR/NEXT loop it adds pointers to the basic stack so it can "Return" from the GOSUB or get back to the start of the FOR/NEXT loop.  When you issue a RETURN, the BASIC interpreter reads the most recent (last in first out) GOSUB pointer,  deletes it from the BASIC stack, and then jumps to the location of the pointer to bring code execution back to the point right after the GOSUB statement.    Likewise, when a FOR/NEXT loop completes its run (i.e., the value of the indexing variable (lets call it "I")  has reached the final end value (call it "Z" for purposes of this discussion), i.e.,  FOR I = 1 to Z" value, then the BASIC interpreter clears out the pointer in the BASIC stack that it was using to jump back to the beginning of the loop when it reached the "NEXT" operator.      
    If you "GOSUB" somewhere, and then never execute a corresponding RETURN for that GOSUB, but somehow wind up back at that code line and issue that same GOSUB line again, you'll add a new pointer to the BASIC stack without the old one getting deleted.   If you exit a FOR/NEXT loop OTHER than by the loop completing of its own accord, then the FOR/NEXT pointers won't get removed.     
    BASIC tries to help you with this.    If you start a FOR/NEXT loop in a subroutine reached by GOSUB, then all pointers related to that FOR/NEXT loop are cleaned out (whether those loops exited normally or not) when the interpreter executes the RETURN statement from that subroutine. 
    But generally, you need to be aware of GOSUB/RETURN and FOR/NEXT finishing "the right way" as you code.  Think of these as "the other shoe must drop" situations, you have to 'close out the cycle" cleanly or the BASIC stack grows until it has no room for the next FOR/NEXT pointer or GOSUB/RETURN pointer.   
    Another thing:  Although you can nestle FOR/NEXT loops (I.e., FOR Y=0to25:FORX=0to39: [stuff]: NEXTX:NEXTY) C64 BASIC limits this to 10 maximum, or again it errors out.   And the error in all these cases will be:
    "OUT OF MEMORY ERROR"
    One thing novice BASIC programmers do is think that they need to use a different variable name for every FOR/NEXT loop.   That's not so, and it actually inadvertently avoids another cleanup tool built into C64 basic.   Suppose I have a loop early in my program that is indexed by "I'  ("FOR I = ...") and that I use to read a bunch of data before branching to my main program.     But suppose that I had a brain fart and coded my DATA reader to exit with a GOTO when it got to  a "-1" I put at the end of my values.    Boom, I've left a FOR/NEXT pointer from a premature FOR/NEXT exit on the BASIC stack.    But suppose I then get to my splash screen routine, and need to loop through 10 messages for the user, and decide to use the "I" variable again to index that FOR/NEXT loop.   BINGO!   Whenever you start a new FOR/NEXT using the indexing variable of another FOR/NEXT loop that has been left on the stack, the interpreter cleans up the mess from the OLD loop before starting the new one. 
    The lesson is to look at your code and make sure you're using the same indexing variable over again for subsequent loops (assuming the original loops are done and the indexer variable name from an earlier loop has not been defined for something else).   
    There's one more benefit to this for C64  BASIC programmers.   If you throw away another scaler variable every time you start a new FOR/NEXT loop, even if there is never again a use for the variables you used to index prior loops, you begin to slow down your program. 
    Every scaler variable (not an array) is put in variable-land the first time you use it.    But this is not like a phonebook.   The computer doesn't know the memory address for any particular variable.   It sticks a sequential list of scaler variables and the addresses of their contents right after BASIC in memory, and it uses the "nope, nope, nope" approach to check each variable to see if that's the one you just told it to use.   So if you make 10 different scaler variables, and ask it to use the last one, the interpreter has to scan through all 9 of the earlier created ones EVERY TIME before it gets to the pointer for the one you now want to use.   
    Anyway, I think from your description you'll find that something in your code is smashing the BASIC stack.   Look for early loop exits and GOSUBS that you accidentally are treating like GOTOs. 
    EDITED TO ADD:    I could be wrong about this part, but I THINK that the GOSUB/RETURN and FOR/NEXT issues can compound each other.   That is to say, although a RETURN from GOSUB cleans out any FOR/NEXTs started during that subroutine, a REPEAT GOSUB to the same routine that contains a FOR/NEXT loop (without the prior GOSUB getting RETURN'd properly) will cause the subroutine to add new FOR/NEXT pointers since it won't look back in the stack past the GOSUB pointer for that subroutine to see that it needs to clean out a FOR/NEXT.    This could be insidious because even if you use the same looping index variable, the stack will have multiple pointers for it.   Lesson:   Start with your GOSUBs as your very first debugging step and make absolutely sure you don't have any that aren't getting "RETURN" statements. 
×
×
  • Create New...

Important Information

Please review our Terms of Use