This is an archived, read-only copy of the United-TI subforum , including posts and topic from May 2003 to April 2012. If you would like to discuss any of the topics in this forum, you can visit Cemetech's z80 & ez80 Assembly subforum. Some of these topics may also be directly-linked to active Cemetech topics. If you are a Cemetech member with a linked United-TI account, you can link United-TI topics here with your current Cemetech topics.

This forum is locked: you cannot post, reply to, or edit topics. Z80 & 68k Assembly => z80 & ez80 Assembly
Author Message
bossier330


Newbie


Joined: 28 Jun 2006
Posts: 28

Posted: 15 Mar 2007 05:57:10 pm    Post subject:

i'm trying to create a number between 2 bounds and store it somewhere using as few b_calls as possible. here's my code. i keep gettin an ERR:INVALID DIM
basically, there is a list or prices that are in word format (.dw). the lower bound is the first number and the upper is the next. the temp location is so i can save the lower bound (to add to the random number times the difference of the upper and lower bounds) without using a b_call.


Code:
   ld   b,8;
   ld   ix,prices;
   ld   de,randBounds;
randomPrices:
   push   bc;
   ld   a,(de);
   ld   l,a;
   inc   de;
   ld   a,(de);
   ld   h,a;
   inc   de;
   ld   (temp),hl;
   ld   b,h;
   ld   c,l;
   ld   a,(de);
   ld   l,a;
   inc   de;
   ld   a,(de);
   ld   h,a;
   inc   de;
   scf
   ccf
   sbc   hl,bc
   push   de;
   B_CALL(_SetXXXXOP2);
   B_CALL(_OP2ToOP5);
   B_CALL(_Random);
   B_CALL(_OP5ToOP2);
   B_CALL(_FPMult);
   ld   d,0;
   B_CALL(_Round);
   B_CALL(_ConvOP1);
   ld   hl,(temp);
   add   hl,de;
   ld   a,l;
   ld   (ix),a;
   ld   a,h;
   ld   (ix + 1),a;
   inc   ix;
   inc   ix;
   pop   de;   
   pop   bc;
   djnz   randomPrices;


if anyone can help that would be great.


Last edited by Guest on 16 Mar 2007 10:11:16 am; edited 1 time in total
Back to top
Recursive Acronym


Advanced Member


Joined: 11 Dec 2006
Posts: 499

Posted: 16 Mar 2007 10:19:28 am    Post subject:

The best way to get random integers is to use Ion and its random number routine. You could also download the ion.zip file, open the source to Ion, and copy the code for the random routine into your program.

Last edited by Guest on 16 Mar 2007 10:21:37 am; edited 1 time in total
Back to top
WikiGuru
ADOS (Attention deficit... Oh! Shiny!)


Elite


Joined: 15 Sep 2005
Posts: 923

Posted: 16 Mar 2007 04:22:38 pm    Post subject:

You should be able to create a random number generator without any bcall's. Here's a simple method:

  1. Use hl to point to a place in memory stored in the seed, or start
  2. load that value into the seed, and then find that place in memory again
  3. re-load value into seed
  4. repeat this however many times you want

Code:
;Example code
;a holds random number
;
randInt:
 ld hl,seed                    ;get address in seed
 ld b,(hl)
 inc hl
 ld c,(hl)

 ld a,(bc)                     ;get new seed
 ld (seed),a
 inc bc
 ld (seed+1),a

 jr randInt                    ;add own conditions for exiting loop

;after done, get value pointed to by seed
 ld hl,seed
 ld a,(hl)

seed:
 .dw 0


Note that this code is not complete, you'll have to implement limits yourself and other tid-bits you want to add. Also note that I haven't tested it, so their might be some errors.

Also note that if this is for a program to be run solo, then you'll have to implement some way that will make it so the seed doesn't always start at 0 (or what ever value you set it to).


Last edited by Guest on 16 Mar 2007 04:26:04 pm; edited 1 time in total
Back to top
bossier330


Newbie


Joined: 28 Jun 2006
Posts: 28

Posted: 16 Mar 2007 07:01:38 pm    Post subject:

thanks, but i'm trying to create random 2byte integers between 2 2byte bounds. like i want to have random*(2byteHi-2byteLow)+2byteLow. i already have a "seed" table and the upper bounds. for example:


Code:
seeds:
.dw 500,1000;
.dw 450,2000;
Back to top
WikiGuru
ADOS (Attention deficit... Oh! Shiny!)


Elite


Joined: 15 Sep 2005
Posts: 923

Posted: 16 Mar 2007 10:09:55 pm    Post subject:

Same principle, you just need to load the address after it into the next register:

Code:
;Example code
;bc holds random number
;
randInt:
ld hl,seed                   ;get address in seed
ld b,(hl)
inc hl
ld c,(hl)

ld a,(bc)                    ;get new seed
ld (seed),a
inc bc
ld (seed+1),a

jr randInt                   ;add own conditions for exiting loop

;after done, get value pointed to by seed
ld hl,seed
ld b,(hl)
inc hl
ld c,(hl)

;check if in bounds

ld hl,upper                     ;upper bounds
ld a,(hl)
cp b
jr c,randInt                    ;get new number if too big
jr nz,testSmall              ;if not equal, no need to check other 8 bits

inc hl
ld a,(hl)
cp c
jr c,randInt

testSmall:
ld hl,lower
ld a,(hl)
cp b
jr z,test2small            ;test lower 8 bits if equal
jr nc,randInt              ;jump upper 8 bits
ret                            ;number is okay, return

test2small:
inc hl
ld a,(hl)
cp c
ret z                          ;return if equal
jr nc,randInt              ;check if smaller
ret                            ;number is okay

lower:
.dw 10

upper:
.dw 500

seed:
.dw 0

again, I haven't tested this code, so there might be some errors.
Back to top
Jim e


Advanced Member


Joined: 05 Sep 2005
Posts: 360

Posted: 16 Mar 2007 11:20:18 pm    Post subject:

wow...seriously. Not only will that not generate a random number but its possible it may never leave the loop.


@bossier330:
Call ion random twice.


Code:
;in
;BC upper bound
;
;out
; hl = Random number (  0 <= HL <= BC )

random16:
        push bc
        inc b
        call ionrandom
        ld h,a
        pop bc
        cp b
        ld b,0
        jr nz,skipsmlr
        ld b,c
        inc b
skipsmlr:
        call ionrandom
        ld l,a
        ret


Last edited by Guest on 16 Mar 2007 11:47:25 pm; edited 1 time in total
Back to top
bossier330


Newbie


Joined: 28 Jun 2006
Posts: 28

Posted: 17 Mar 2007 07:18:53 am    Post subject:

can you pute comments in your code? i'm getting a little confused.
Back to top
bossier330


Newbie


Joined: 28 Jun 2006
Posts: 28

Posted: 17 Mar 2007 07:40:24 am    Post subject:

nevermind. thanks for your help.
Back to top
DarkerLine
ceci n'est pas une |


Super Elite (Last Title)


Joined: 04 Nov 2003
Posts: 8328

Posted: 17 Mar 2007 10:29:33 am    Post subject:

Jim_e: your code is slightly skewed in its probability. The less-than-256 numbers on the high end of the range have the same probability of occurring as any 256 numbers elsewhere in the range. This could have an extreme case of 1 number being 256 times more likely to be chosen than any other.

Granted, I can't think of a better way to do it. You could, of course, round the number up to the nearest 256, then pick numbers until it's in the right range, but that could potentially take any amount of time (though it probably won't).
Back to top
Jim e


Advanced Member


Joined: 05 Sep 2005
Posts: 360

Posted: 17 Mar 2007 11:02:16 am    Post subject:

DarkerLine wrote:
Jim_e: your code is slightly skewed in its probability. The less-than-256 numbers on the high end of the range have the same probability of occurring as any 256 numbers elsewhere in the range. This could have an extreme case of 1 number being 256 times more likely to be chosen than any other.
I don't see how.

DarkerLine wrote:
Granted, I can't think of a better way to do it. You could, of course, round the number up to the nearest 256, then pick numbers until it's in the right range, but that could potentially take any amount of time (though it probably won't).
what?
Back to top
DarkerLine
ceci n'est pas une |


Super Elite (Last Title)


Joined: 04 Nov 2003
Posts: 8328

Posted: 17 Mar 2007 11:30:57 am    Post subject:

Say you're picking a number between 0 and 256. The routine will get the MSB to be either a 0 or a 1 (with presumably equal probability). If it's a 0, then the routine picks the LSB to be a random number 0-255, yielding a result from 0 to 255. If it's a 1, then the routine picks the LSB to be a random number 0-0, yielding a result from 256 to 256. These two outcomes are equally likely. Making every number 0..255 have a probability of 1/512, and 256 have a probability of 256/512 = 1/2. Of course, this is the most extreme example possible, so it's really not that bad.


Unless I'm misunderstanding something about your code?


Last edited by Guest on 17 Mar 2007 11:32:48 am; edited 1 time in total
Back to top
Jim e


Advanced Member


Joined: 05 Sep 2005
Posts: 360

Posted: 17 Mar 2007 11:46:13 am    Post subject:

hmmm...yeah that is true. It probably won't be a problem. I suppose another solution could be generating 2 random bytes making a word, and dividing by 2 until it is less than the upper bound.


Code:
rand16:
        ld b,0
        call ionrandom
        ld d,a
        ld b,0
        call ionrandom
        ld e,a
rand16loop:
        ld h,d
        ld l,e
        or a
        sbc hl,bc
        ret c
        srl d
        rr e
        jp rand16loop
Back to top
DarkerLine
ceci n'est pas une |


Super Elite (Last Title)


Joined: 04 Nov 2003
Posts: 8328

Posted: 17 Mar 2007 12:00:13 pm    Post subject:

Even worse, as it chooses high numbers consistently higher than low ones (sorry about picking your random numbers apart like this). For example, suppose you're looking for a random number 0..511. There's only one way to generate a number 0..255, and that is if it comes up from the start. It can't be generated by shifting another number, since any number that could be shifted into the range 0..255 was already in the correct range, and therefore already returned as a number 256..511.

On the other hand, there are 8 ways to generate a number 256..511. It could come up from the start, or from shifting 1 to 7 times. This would make numbers 256..511 8 times as likely to come up (with a probability of 1/288 as opposed to 1/2304).
Back to top
Jim e


Advanced Member


Joined: 05 Sep 2005
Posts: 360

Posted: 17 Mar 2007 12:17:05 pm    Post subject:

Theres no satisfying you is there. Especially considering that using ion random in a loop has the randomness of reading bytes from memory.

Well the only other thing is actually multiplying a 16bit seed with the 16bit upper, May as well rewrite the ionrandom.
Back to top
bossier330


Newbie


Joined: 28 Jun 2006
Posts: 28

Posted: 17 Mar 2007 12:59:27 pm    Post subject:

i really want to do this:

load the lower word to de
load the upper word to hl
subtract the two
set hl to OP2
copy OP2 to OP5 (save it )
make a random number 0<n<1 to OP1
mvoe OP5 back to OP2
multiply OP1 by OP2
set OP2 to de
add lower to de
save new number to RAM
Back to top
DarkerLine
ceci n'est pas une |


Super Elite (Last Title)


Joined: 04 Nov 2003
Posts: 8328

Posted: 17 Mar 2007 01:06:30 pm    Post subject:

Jim e wrote:
Theres no satisfying you is there.  Especially considering that using ion random in a loop has the randomness of reading bytes from memory.
Not if there's interrupts. Not that I'm recommending doing that, I think it's stupid myself.
Quote:
Well the only other thing is actually multiplying a 16bit seed with the 16bit upper, May as well rewrite the ionrandom.
And be forced to write a 16bit multiplication routine...

Then again, all this depends on what the random number generator should be used for. More information would tell us what aspects of randomness aren't essential.

bossier330 wrote:
i really want to do this:

load the lower word to de
load the upper word to hl
subtract the two
set hl to OP2
copy OP2 to OP5 (save it )
make a random number 0<n<1 to OP1
mvoe OP5 back to OP2
multiply OP1 by OP2
set OP2 to de
add lower to de
save new number to RAM
[post="99030"]<{POST_SNAPBACK}>[/post]
This would probably be the best more-or-less-random way in terms of size. In terms of speed, it would be the worst - the TI random routine is so slow BASIC can use it as a delay.

A good compromise in my opinion would be to bcall(_Random) then use the random floating point data directly to get a few bytes of randomness. The annoying aspect of that is converting decimal data to hexadecimal data without loss of randomness.


Last edited by Guest on 17 Mar 2007 01:13:12 pm; edited 1 time in total
Back to top
Jim e


Advanced Member


Joined: 05 Sep 2005
Posts: 360

Posted: 17 Mar 2007 02:38:09 pm    Post subject:

DarkerLine wrote:
Not if there's interrupts. Not that I'm recommending doing that, I think it's stupid myself.
Chances of an interrupt happening there can be pretty slim, either way interrupts are fairly uniform after a while.

Quote:
Then again, all this depends on what the random number generator should be used for. More information would tell us what aspects of randomness aren't essential.
I think its excessive, ion random is good enough.

Quote:
bossier330 wrote:
i really want to do this:
load the lower word to de
load the upper word to hl
subtract the two
set hl to OP2
copy OP2 to OP5 (save it )
make a random number 0<n<1 to OP1
mvoe OP5 back to OP2
multiply OP1 by OP2
set OP2 to de
add lower to de
save new number to RAM
[post="99030"]<{POST_SNAPBACK}>[/post]
This would probably be the best more-or-less-random way in terms of size.
terms of size, not sure about that.

Still just use ion random and a small mod routine would be fairly cheap.
Back to top
Display posts from previous:   
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
    »
» View previous topic :: View next topic  
Page 1 of 1 » All times are UTC - 5 Hours

 

Advertisement