converting decimal into binary string

The place for codemasters or beginners to talk about programming any language for the Spectrum.
Post Reply
User avatar
777
Manic Miner
Posts: 512
Joined: Fri Jun 26, 2020 11:23 am
Location: sw uk

converting decimal into binary string

Post by 777 »

so like the opposite of the bin function. in basic if possible. it only needs to be an 8 bit number. like a dec$ function?
Last edited by 777 on Fri Dec 11, 2020 5:26 pm, edited 1 time in total.
i started programming the spectrum when i was 8 :-

1 plot rnd*255,rnd*175
2 goto 1
User avatar
PeterJ
Site Admin
Posts: 6879
Joined: Thu Nov 09, 2017 7:19 pm
Location: Surrey, UK

Re: converting decimal into binary

Post by PeterJ »

You would need to code it @777

An easy method of converting decimal to binary number equivalents is to write down the decimal number and to continually divide-by-2 (two) to give a result and a remainder of either a “1” or a “0” until the final result equals zero
User avatar
777
Manic Miner
Posts: 512
Joined: Fri Jun 26, 2020 11:23 am
Location: sw uk

Re: converting decimal into binary

Post by 777 »

PeterJ wrote: Fri Dec 11, 2020 5:05 pm You would need to code it @777

An easy method of converting decimal to binary number equivalents is to write down the decimal number and to continually divide-by-2 (two) to give a result and a remainder of either a “1” or a “0” until the final result equals zero
i wouldnt know where to begin
i started programming the spectrum when i was 8 :-

1 plot rnd*255,rnd*175
2 goto 1
User avatar
PeterJ
Site Admin
Posts: 6879
Joined: Thu Nov 09, 2017 7:19 pm
Location: Surrey, UK

Re: converting decimal into binary string

Post by PeterJ »

Try this [mention]777[/mention]

T contains the number you want to convert (between 0 and 255)

[mention]TMD2003[/mention] has encouraged me to explore BASIC more. I had forgotten much of what I had learnt as a child!

Image

There is an SZX snapshot here (128K format):

https://gofile.io/d/YYNLVC
User avatar
uglifruit
Manic Miner
Posts: 703
Joined: Thu Jan 17, 2019 12:41 pm
Location: Leicester
Contact:

Re: converting decimal into binary string

Post by uglifruit »

It's quite possible that this is a worse way of doing it, but it might prove useful:

Code: Select all

10 INPUT x:PRINT x,
20 GOSUB 200:PRINT b$
30 GOTO 10

199 REM DEC to BIN.  Input X, Output B$, corrupts C,X
200 LET b$="":LET c=128							; sets up a blank string, and a counter.
									; counter=128 gives an 8 bit number, 32768 would be 16 bit
210 LET b$=b$+str$ (x>=c)						; if x is greater or equal to counter, then add a "1" to the string, otherwise add "0"
220 LET x=x-(x>=c)*c							; reduce x by the counter value, if x is >= counter (i.e. if the bit was set)
230 LET c=c/2								; halve the counter
240 IF c>=1 THEN GOTO 210						; if the counter is 1 or more, then move to the next bit
250 RETURN
CLEAR 23855
User avatar
uglifruit
Manic Miner
Posts: 703
Joined: Thu Jan 17, 2019 12:41 pm
Location: Leicester
Contact:

Re: converting decimal into binary string

Post by uglifruit »

Actually a bit easier to understand, and a slightly quicker, I think:

Code: Select all

10 INPUT X:PRINT X,
20 GOSUB 200:PRINT B$
30 GOTO 10

199 REM DEC TO BIN.  INPUT X, OUTPUT B$, CORRUPTS C,X
200 LET B$="":LET C=128							; b$ set as blank string.  counter c gives number of bits
											; c=128 8 bit number, c=32768 16 bit number
210 IF X>=C THEN LET B$=B$+"1":LET X=X-C:GOTO 230	; Set the string and adds a "1" if it's greater than counter
											; and reduces X by the current counter value
220 LET B$=B$+"0"								; Otherwise adds a "0" to the output string
230 LET C=C/2:IF C>=1 THEN GOTO 210				; Halves the counter, and sees if there is more bits to do!
250 RETURN
CLEAR 23855
User avatar
TMD2003
Rick Dangerous
Posts: 2043
Joined: Fri Apr 10, 2020 9:23 am
Location: Airstrip One
Contact:

Re: converting decimal into binary string

Post by TMD2003 »

[mention]777[/mention]: I started programming the Spectrum when I was 8 as well (and the ZX81 at 4 - you can imagine what that looked like). I started programming the Spectrum in machine code at... 41. I might not be fast, but I get there in the end!

This is one of those problems that's an ideal opportunity to solve along the course of my machine code quest. Only thing is, I've not yet reached the point where I can read BASIC-assigned variables with machine code - but I can do most of it, just POKE one value, define an empty string b$, and execute the code. I've taken 64 bytes, which are assembled from 65000 to 65064 in this routine. As it stands, with the fixed numbers in the DATA lines, this has to stay at 65000, but the assembler code I've posted below the BASIC listing can be pasted into SPIN and assembled anywhere, and it'll work out all the new addresses to pick the values from and JR Z to.

Essentially, assemble to ad, POKE the value v to be converted into ad+65, and LET l=USR ad. The machine code will initially poke the value 48 into addresses ad+66 to ad+73, then analyse the value v and for every 1 in the binary value, it will increase the corresponding address from 48 to 49. All the BASIC then has to do is PEEK the addresses and add CHR$ of the CODE stored at that address to b$.

I've made this loop v from 0 to 255 so it displays all the values and shows how fast the routine is. You can paste this into a text editor, get shot of the REMs, bunch multiple statements into fewer lines, and cut out anything extraneous. Then paste that into BASin, renumber it as required, and save it as a Z80 snapshot. The code can saved and reloaded, just don't forget to CLEAR one less than the start address.

Code: Select all

  10 REM decimal to binary with machine code
  20 CLEAR 64999
  30 LET ad=65000
  40 GO SUB 9000
  50 FOR v=0 TO 255
  60 LET b$=""
  70 POKE ad+65,v
  80 LET l=USR ad
  90 FOR n=ad+66 TO ad+73
 100 LET b$=b$+CHR$ (PEEK n)
 110 NEXT n
 120 POKE 23692,255
 130 PRINT v;TAB 4;b$
 140 NEXT v
 999 STOP
9000 REM machine code
9010 RESTORE 9900
9020 FOR n=ad TO ad+64
9030 READ byte
9040 POKE n,byte
9050 NEXT n
9060 RETURN
9900 DATA 33,42,254,6,8,54,48,35,16,251
9910 DATA 58,41,254,33,42,254,203,127,40,1,52,35,203,119,40,1,52,35,203,111,40,1,52,35,203,103,40,1,52
9920 DATA 35,203,95,40,1,52,35,203,87,40,1,52,35,203,79,40,1,52,35,203,71,40,2,52,35,201
Meanwhile, here's what I wrote in SPIN's assembler to make it work, with annotations as to what the DATA lines correspond to...

Code: Select all

; 9900 DATA...

init:	ld hl,b7	; put address "b7" into HL
	ld b,8		; loop 8 times
loop1:	ld (hl),48	; POKE address held in HL with 48
	inc hl		; point HL to next address
	djnz loop1	; DEC B and loop until B=0
; eight addresses after STORE are loaded with the CODE for "0"

; 9910 DATA...

main:	ld a,(store)	; put the stored value into accumulator	
ch7:	ld hl,b7	; put HL back to address "b7" again
	bit 7,a		; check bit 7 of A
	jr z,ch6	; if bit 7 is 0, skip the next lines
	inc (hl)	; if bit 7 is 1, increase value held in "b7" by 1, i.e it is now CODE "1"
ch6:	inc hl		; first now increase the address HL points to, to "b6"
	bit 6,a		; and so on...
	jr z,ch5
	inc (hl)
ch5:	inc hl
	bit 5,a
	jr z,ch4
	inc (hl)
ch4:	inc hl
	bit 4,a
	jr z,ch3
	inc (hl)

; 9920 DATA...

ch3:	inc hl
	bit 3,a
	jr z,ch2
	inc (hl)
ch2:	inc hl
	bit 2,a
	jr z,ch1
	inc (hl)
ch1:	inc hl
	bit 1,a
	jr z,ch0
	inc (hl)
ch0:	inc hl
	bit 0,a
	jr z,finale
	inc (hl)
	inc hl
finale:	ret

; these aren't in the DATA statements - you POKE the value shown, the machine code works out the other eight bytes

store:	defb 0	; start address + 65 - POKE value to convert here
b7:	defb 0	; these will be 48 (CODE "0") or 49 (CODE "1") at end of routine. 
b6:	defb 0
b5:	defb 0
b4:	defb 0
b3:	defb 0
b2:	defb 0
b1:	defb 0
b0:	defb 0
Spectribution: Dr. Jim's Sinclair computing pages.
Features my own programs, modified type-ins, RZXs, character sets & UDGs, and QL type-ins... so far!
User avatar
Manu128k
Dizzy
Posts: 83
Joined: Tue Aug 13, 2019 9:45 pm
Location: Spain
Contact:

Re: converting decimal into binary string

Post by Manu128k »

If the number would always be between 0 and 255 and you can spare a single square of the screen for a moment, then there is a much simpler way IMHO, maybe faster too. Just POKE it to the screen, and read 1 bit each time with point(). No divisions and you got your number in binary format. If you think this approach could be of some use for you, I can elaborate further.
User avatar
uglifruit
Manic Miner
Posts: 703
Joined: Thu Jan 17, 2019 12:41 pm
Location: Leicester
Contact:

Re: converting decimal into binary string

Post by uglifruit »

Completely stealing [mention]TMD2003[/mention]'s the idea of doing it in hybrid m/c and BASIC

I thought, why not modify the BASIC program itself?
I wrote a quick assembly routine to that modfies LINE 1 of the program from LET b$="FAKETEXT" to LET b$="00101100" (or whatever the required string is).
Very quick in operation, just one POKE required with the input variable, then just RANDOMIZE USR address of routine, followed by GOSUB 1 to get the result in b$.

Code: Select all

 ;                                              ; DEC to BIN
                                                ; LINE 1 of BASIC should be    1 LET b$="12345678":RETURN

                                                ; This is a RELOCATABLE routine

                org     65000

                ld      a,0                     ;  ADDRESS of this routine + 1 is POKED with number to be BIN'd

                ld      hl,(23635)              ;  Address Of The System Variable pointing at the BASIC Program (PROG)
                ld      de,8                    ;  first line of BASIC should be LET b$="12345678" starts at that System Variable + 9
                add     hl,de                   ;  HL now points at the first byte of the string


                ld      b,8                     ; counter 8 times
fill_loop:
                inc     hl
                ld      (hl),"0"                ; fill the string with "0"s to start with
                djnz    fill_loop               ; do it again if counter is not zero

                                                ; HL currently points at address of last character in string

                ld      b,8                     ; counter
                                                ; A still contains the number
change_loop:
                rra                             ; rotate bitwise right.  Leftmost bit becomes carry flag
                jr      nc,dont_change          ; if carry flag isn't set, then don't do anything
                ld      (hl),"1"                ; but if it IS set, then make the string character a '1'
dont_change:
                dec     hl                      ; move to the previous string address
                djnz    change_loop             ; do this 8 times in total

                ret                             ; back to BASIC
If you'd like it in the BASIC program itself, then it's only 27 bytes long.
(defb 62,0,42,83,92,17,8,0,25,6,8,35,54,48,16,251,6,8,31,48,2,54,49,43,16,248,201)

For example:
Image

.z80 file of the above, to have a play:
https://1drv.ms/u/s!AmvYCHV8PMQkhCZLASR ... 4?e=ghfoU3


And here it is doing all the numbers from 0-255, very rapidly, from BASIC
Image

.z80 file of that just here
https://1drv.ms/u/s!AmvYCHV8PMQkhCfnN_d ... W?e=xTBs18


I can't seem to post pics at a useful size. Apologies.
edited: because I'm an idiot.
CLEAR 23855
User avatar
uglifruit
Manic Miner
Posts: 703
Joined: Thu Jan 17, 2019 12:41 pm
Location: Leicester
Contact:

Re: converting decimal into binary string

Post by uglifruit »

I wasn't happy about the GOSUB to the first line to call the m/code routine. The RETURN statement got in the way, when running.

I realised that if I made the first line a DEF FN statement :
1. it'll be skipped when the program is RUN
2. didn't require an ugly RETURN statement
3. it can be made to run the m/code routine, that modifies itself.

So a more elegant BASIC version would be;

Code: Select all

1 DEF FN b$()=("" AND USR 65000)+"XXXXXXXX"     ; this XXXXXXXX text string is changed when the routine at 65000 is called.
                                                               ; The bracketed section will be interpreted and the routine at 65000 called 
                                                               ; *before* the rest of the string (that is changed) is appended
10 FOR A=0 TO 255
20 POKE 65001,A
30 PRINT AT 10,0;A,FN B$()
40 NEXT A
50 STOP

99 REM SET UP THE MACHINE CODE ROUTINE AT 65000
100 CLEAR 64999:FOR Z=65000 TO 65026:READ X:POKE Z,X:NEXT Z
110  DATA 62,0,42,83,92,17,28,0,25,6,8,35,54,48,16,251,6,8,31,48,2,54,49,43,16,248,201
.z80 Snapshot here: https://1drv.ms/u/s!AmvYCHV8PMQkhChkkXL ... i?e=glTlPM


The only change to the assembly routine is where the text string is now located with respect to the start of the basic program. It is now 29 bytes in, assuming the 1st line is as written.

Code: Select all

               org     65000
                ld      a,0                       ; ADDRESS_of_this_routine + 1 is POKED with number to be converted to a BIN string
                ld      hl,(23635)             ; Address Of The System Variable pointing at the BASIC Program (PROG)
                ld      de,28                ; the first line of BASIC should be 1 DEF FN b$=("" AND USR 65000)+"XXXXXXXX" 
                			             ; meaning the text string starts at that System Variable + 29
                add     hl,de                   ;  HL now points at the first byte of the string


                ld      b,8                     ; counter 8 times
fill_loop:
                inc     hl
                ld      (hl),"0"                ; fill the string with "0"s to start with
                djnz    fill_loop               ; do it again if counter is not zero

                                                ; HL currently points at address of last character in string

                ld      b,8                     ; counter
                                                ; A still contains the number
change_loop:
                rra                             ; rotate bitwise right.  Leftmost bit becomes carry flag
                jr      nc,dont_change          ; if carry flag isn't set, then don't do anything
                ld      (hl),"1"                ; but if it IS set, then make the string character a '1'
dont_change:
                dec     hl                      ; move to the previous string address
                djnz    change_loop             ; do this 8 times in total

                ret                             ; back to BASIC
CLEAR 23855
User avatar
PeterJ
Site Admin
Posts: 6879
Joined: Thu Nov 09, 2017 7:19 pm
Location: Surrey, UK

Re: converting decimal into binary string

Post by PeterJ »

There is another good example in BASIC over on WoS:

https://worldofspectrum.org/forums/prof ... 3/JianYang
User avatar
777
Manic Miner
Posts: 512
Joined: Fri Jun 26, 2020 11:23 am
Location: sw uk

Re: converting decimal into binary string

Post by 777 »

thanks guys, got it sussed.thank you.
i started programming the spectrum when i was 8 :-

1 plot rnd*255,rnd*175
2 goto 1
Post Reply