two's complement and binary output

Notices and updates
Locked
cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

two's complement and binary output

Post by cormullion »

I'm trying to write a binary output function that does two's complements as well. It sort of works, but it feels like hard work - is there an easier way?

Code: Select all

(define (binary n (width 24) , temp)
	(print (format {%6d } n))
	(set 'temp '() 'x n)
	(if (< n 0) (inc 'x))
	(until (= x 0)
		(push (string (% (abs x) 2)) temp)
		(set 'x (/ x 2)))
	(set 'result (format (string {%0} width {s}) (join temp)))
	(and 
		(< n 0)
		(replace "1" result "x")
		(replace "0" result "1")
		(replace "x" result "0"))
 	(println result))


(for (i -10 10)
	(binary i 16))
	
   -10 1111111111110110
    -9 1111111111110111
    -8 1111111111111000
    -7 1111111111111001
    -6 1111111111111010
    -5 1111111111111011
    -4 1111111111111100
    -3 1111111111111101
    -2 1111111111111110
    -1 1111111111111111
     0 0000000000000000
     1 0000000000000001
     2 0000000000000010
     3 0000000000000011
     4 0000000000000100
     5 0000000000000101
     6 0000000000000110
     7 0000000000000111
     8 0000000000001000
     9 0000000000001001
    10 0000000000001010


Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

It gets easier if you discover the bits in the number directly and then shift them out one by one:

Code: Select all

(define (binary n (width 24) , temp)
    (dotimes (i width)
        (push (& n 1) temp)   
        (set 'n (>> n)))
    (join (map string temp)))

(for (n -10 10) (println (format "%6d %s" n (binary n 16))))

   -10 1111111111110110
    -9 1111111111110111
    -8 1111111111111000
    -7 1111111111111001
    -6 1111111111111010
    -5 1111111111111011
    -4 1111111111111100
    -3 1111111111111101
    -2 1111111111111110
    -1 1111111111111111
     0 0000000000000000
     1 0000000000000001
     2 0000000000000010
     3 0000000000000011
     4 0000000000000100
     5 0000000000000101
     6 0000000000000110
     7 0000000000000111
     8 0000000000001000
     9 0000000000001001
    10 0000000000001010
Lutz

ps: exchanged (if (= 1 (& n 0x1)) 1 0) for (& n 1) after riickyboy's remark
Last edited by Lutz on Tue Nov 28, 2006 5:00 pm, edited 2 times in total.

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

Very nice - thanks!

rickyboy
Posts: 607
Joined: Fri Apr 08, 2005 7:13 pm
Location: Front Royal, Virginia

Post by rickyboy »

Very nice Lutz.

BTW, you can replace '(if (= 1 (& n 0x1)) 1 0)' with '(& n 0x1)' in the body of 'binary' and it will work the same.

I also liked how Lutz separated the 'print(ln)'ing of the result with the building of the result string. I like this design. I too try to avoid "embedded prints" in "building" functions, because I have always seemed to find a use for the result string either before, or instead of, printing it. Good job!

--Rick
(λx. x x) (λx. x x)

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

Yes, I must plead guilty to sometimes putting print statements in my functions! It certainly doesn't promote the building-block approach. But occasionally it provides a bit of clarity - when writing tutorials, for example - if you use a function that has an all-in-one "apply-process-report" action. I'm writing this as we speak:

Code: Select all

(binary (^ 4 5))
 1   000000000000000000000001 

(binary (| 4 5)) 
 5   000000000000000000000101
which I quite like.

My other excuse is that I use a text editor too much... ;-)

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

Most try their programs interactively, loading from the commandlione and then exeuting the function. The editor is open in a different window.

Code: Select all

newLISP v.9.0.4 on OSX UTF-8, execute 'newlisp -h' for more info.

> (load "binary")
(lambda (n (width 24) , temp) 
 (dotimes (i width) 
  (push (& n 1) temp) 
  (set 'n (>> n))) 
 (join (map string temp)))
> (binary 10)
"000000000000000000001010"
> 
The 'load' command then comes back with the return value of the last evaluation in the file, which was a 'define' statement returning a the lambda expression.

You then edit the file, save it and do: cursor-up-up <enter> in the newLISP terminal to get the (load "binary") line back. Then cursor-up-up <enter> again to execute: (binary 10).

Sometimes I do:

Code: Select all

>!vi binary

; or on Mac OS X
 
>!open -e binary
and call up my editor (vi) inside the same newLISP terminal window. When I quit the editor I am back in the newLISP command line. Another advantage of this approach is that inside the newLISP terminal the tab-key expands to file names in the same directory so hitting tab after: >!vi bin will expand the bin to binary.

Lutz

Fanda
Posts: 253
Joined: Tue Aug 02, 2005 6:40 am
Contact:

Post by Fanda »

I am using text editor and newLISP-tk:

text editor: modify & save
newLISP-tk: load/reload

by typing interactively (binary ...) in newLISP-tk, I get results without printing them.

------
My text editor is PSPad (Win32 only)
http://www.pspad.com/

Lutz, feel free to post a syntax highlighting file for PSPad on newlisp.org. I put the file here:
http://www.intricatevisions.com/download/newLISP.ini

Fanda

Locked