Two's complement: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|J}}: second draft)
(→‎{{header|Raku}}: Add a Raku example)
Line 63: Line 63:
(8#2)#:-3
(8#2)#:-3
1 1 1 1 1 1 0 1</lang>
1 1 1 1 1 1 0 1</lang>

=={{header|Raku}}==
By default Rakus integers are arbitrary sized, theoretically of infinite length. You can't really take the twos complement of an infinitely long number; so, we need to specifically used fixed size integers.

There is a module available from the Raku ecosystem that provides fixed size integer support, named (appropriately enough.) [https://raku.land/github:thundergnat/FixedInt FixedInt].

FixedInt supports fixed bit size integers, not only 8 bit, 16 bit, 32 bit or 64 bit, but ''ANY'' integer size. 22 bit, 35 bit, 191 bit, whatever.

Here we'll demonstrate twos complement on a 57 bit integer.

<lang perl6>use FixedInt;

# Instantiate a new 57(!) bit fixed size integer
my \fixedint = FixedInt.new: :57bits;

fixedint = (2³⁷ / 72 - 5¹⁷); # Set it to a large value

say fixedint; # Echo the value to the console in decimal format
say fixedint.bin; # Echo the value to the console in binary format

fixedint.=C2; # Take the twos complement

say fixedint; # Echo the value to the console in decimal format
say fixedint.bin; # Echo the value to the console in binary format</lang>
{{out}}
<pre>144114427045277101
0b111111111111111110100111011001111000010101110110110101101
761030578771
0b000000000000000001011000100110000111101010001001001010011</pre>


=={{header|Z80 Assembly}}==
=={{header|Z80 Assembly}}==

Revision as of 01:36, 24 July 2022

Task
Two's complement
You are encouraged to solve this task according to the task description, using any language you may know.

Two's complement is an important concept in representing negative numbers. To turn a positive integer negative, flip the bits and add one.


Task

Show how to calculate the two's complement of an integer. (It doesn't necessarily need to be a 32 bit integer.)


6502 Assembly

8-Bit

<lang 6502asm>LDA #%01010101 EOR #255 CLC ADC #1 ;result: #%10101011</lang>

16-bit

<lang 6502asm>myVar equ $20

LDA #3 STA myVar LDA #0 STA myVar+1 ;equivalent C: uint16_t myVar = 3;

negate: LDA myVar+1 EOR #255 STA myVar+1

LDA myVar EOR #255 STA myVar CLC ADC #1 STA myVar

this handles the case if we started with something where the low byte was zero.

LDA myVar+1 ADC #0 STA myVar+1</lang>

8086 Assembly

<lang asm>mov al,17 neg al ;8-bit mov bx,4C00h neg bx ;16-bit</lang>


C

<lang C>int a = 3; a = -a;</lang>

J

J uses twos complement natively: <lang J> -3 _3</lang>

We can see this by extracting bits representing the number. In this example, we limit ourselves to 8 bits:

<lang J> (8#2)#:3 0 0 0 0 0 0 1 1

  (8#2)#:-3

1 1 1 1 1 1 0 1</lang>

Raku

By default Rakus integers are arbitrary sized, theoretically of infinite length. You can't really take the twos complement of an infinitely long number; so, we need to specifically used fixed size integers.

There is a module available from the Raku ecosystem that provides fixed size integer support, named (appropriately enough.) FixedInt.

FixedInt supports fixed bit size integers, not only 8 bit, 16 bit, 32 bit or 64 bit, but ANY integer size. 22 bit, 35 bit, 191 bit, whatever.

Here we'll demonstrate twos complement on a 57 bit integer.

<lang perl6>use FixedInt;

  1. Instantiate a new 57(!) bit fixed size integer

my \fixedint = FixedInt.new: :57bits;

fixedint = (2³⁷ / 72 - 5¹⁷); # Set it to a large value

say fixedint; # Echo the value to the console in decimal format say fixedint.bin; # Echo the value to the console in binary format

fixedint.=C2; # Take the twos complement

say fixedint; # Echo the value to the console in decimal format say fixedint.bin; # Echo the value to the console in binary format</lang>

Output:
144114427045277101
0b111111111111111110100111011001111000010101110110110101101
761030578771
0b000000000000000001011000100110000111101010001001001010011

Z80 Assembly

8-Bit

Zilog Z80

<lang z80>ld a,%00001111 neg ;returns %11110001 in a</lang>

Game Boy <lang z80>ld a,%00001111 cpl ;game boy doesn't have NEG but it has CPL which flips all the bits. inc a ;returns %11110001 in a</lang>

16 Bit

NEG and CPL only work on the accumulator A. The following can be written to work with BC, DE, HL, IX, or IY. <lang z80>xor a ;ld a,0 sub c ld c,a sbc a ;loads &FF into A if "sub c" set the carry (borrow) flag. Otherwise, a remains zero. sub b ld b,a</lang>