Two's complement: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(31 intermediate revisions by 15 users not shown)
Line 13: Line 13:
=={{header|6502 Assembly}}==
=={{header|6502 Assembly}}==
===8-Bit===
===8-Bit===
<lang 6502asm>LDA #%01010101
<syntaxhighlight lang="6502asm">LDA #%01010101
EOR #255
EOR #255
CLC
CLC
ADC #1 ;result: #%10101011</lang>
ADC #1 ;result: #%10101011</syntaxhighlight>
===16-bit===
===16-bit===
<lang 6502asm>myVar equ $20
<syntaxhighlight lang="6502asm">myVar equ $20


LDA #3
LDA #3
Line 39: Line 39:
LDA myVar+1
LDA myVar+1
ADC #0
ADC #0
STA myVar+1</lang>
STA myVar+1</syntaxhighlight>


=={{header|68000 Assembly}}==
=={{header|68000 Assembly}}==
<lang 68000devpac>MOVE.L #3,D0
<syntaxhighlight lang="68000devpac">MOVE.L #3,D0
NEG.L D0 ;D0 = #$FFFFFFFD</lang>
NEG.L D0 ;D0 = #$FFFFFFFD</syntaxhighlight>


=={{header|8086 Assembly}}==
=={{header|8086 Assembly}}==
<lang asm>mov al,17
<syntaxhighlight lang="asm">mov al,17
neg al ;8-bit
neg al ;8-bit
mov bx,4C00h
mov bx,4C00h
neg bx ;16-bit</lang>
neg bx ;16-bit</syntaxhighlight>


=={{header|ALGOL 68}}==
=={{header|ALGOL 68}}==
Line 55: Line 55:
<br>
<br>
Note: BIN a converts a to a BITS (bit-string) value, the NOT operator will flip the bits and the ABS operator will convert back to an integer, so <code>1 + ABS NOT BIN a</code> is a long-winded alternative to <code>-a</code>. Note in Algol 68, the BIN operator cannot be applied to negative integers, so <code>1 + ABS NOT BIN -3</code> won't work.
Note: BIN a converts a to a BITS (bit-string) value, the NOT operator will flip the bits and the ABS operator will convert back to an integer, so <code>1 + ABS NOT BIN a</code> is a long-winded alternative to <code>-a</code>. Note in Algol 68, the BIN operator cannot be applied to negative integers, so <code>1 + ABS NOT BIN -3</code> won't work.
<lang algol68>BEGIN
<syntaxhighlight lang="algol68">BEGIN
INT a := 3;
INT a := 3;
print( ( -a, " ", 1 + ABS NOT BIN a, newline ) )
print( ( -a, " ", 1 + ABS NOT BIN a, newline ) )
END</lang>
END</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 66: Line 66:
=={{header|ALGOL W}}==
=={{header|ALGOL W}}==
{{Trans|ALGOL 68}}
{{Trans|ALGOL 68}}
<lang algolw>begin
<syntaxhighlight lang="algolw">begin
integer a;
integer a;
a := 3;
a := 3;
write( i_w := 1, s_w := 1, -a, 1 + number( not bitstring( a ) ) )
write( i_w := 1, s_w := 1, -a, 1 + number( not bitstring( a ) ) )
end.</lang>
end.</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
-3 -3
-3 -3
</pre>
</pre>

=={{header|ARM Assembly}}==
<syntaxhighlight lang="arm assembly">MOV R0,#0x0000000F
MOV R1,#1
MVN R0,R0 ;flips the bits of R0, R0 = 0xFFFFFFF0
ADD R0,R0,R1 ;R0 = 0xFFFFFFF1</syntaxhighlight>


=={{header|C}}==
=={{header|C}}==
<lang C>int a = 3;
<syntaxhighlight lang="c">int a = 3;
a = -a;</lang>
a = -a;</syntaxhighlight>

=={{header|C++}}==
In C++ the two's complement of an integer 'n' is its arithmetic negation '-n'.

The two's complement of an integer 'n' can also be calculated by adding 1 to its bitwise complement '~n'.
<syntaxhighlight lang="c++">
#include <cstdint>
#include <iostream>
#include <iomanip>
#include <vector>
#include <bitset>

std::string to_hex(const int32_t number) {
std::stringstream stream;
stream << std::setfill('0') << std::setw(8) << std::hex << number;
return stream.str();
}

std::string to_binary(const int32_t number) {
std::stringstream stream;
stream << std::bitset<16>(number);
return stream.str();
}

int32_t twos_complement(const int32_t number) {
return ~number + 1;
}

std::string to_upper_case(std::string str) {
for ( char& ch : str ) {
ch = toupper(ch);
}
return str;
}

int main() {
std::vector<int32_t> examples = { 0, 1, -1, 42 };

std::cout << std::setw(9) << "decimal" << std::setw(12) << "hex"
<< std::setw(17) << "binary" << std::setw(25) << "two's complement" << std::endl;
std::cout << std::setw(6) << "-----------" << std::setw(12) << "--------"
<< std::setw(20) << "----------------" << std::setw(20) << "----------------" << std::endl;

for ( const int32_t& example : examples ) {
std::cout << std::setw(6) << example << std::setw(17) << to_upper_case(to_hex(example))
<< std::setw(20) << to_binary(example) << std::setw(13) << twos_complement(example) << std::endl;
}
}
</syntaxhighlight>
{{ out }}
<pre>
decimal hex binary two's complement
----------- -------- ---------------- ----------------
0 00000000 0000000000000000 0
1 00000001 0000000000000001 -1
-1 FFFFFFFF 1111111111111111 1
42 0000002A 0000000000101010 -42
</pre>

=={{header|Craft Basic}}==
<syntaxhighlight lang="basic">let d = 1234567

dim b[d * -1, d * -1 + 1, -2, -1, 0, 1, 2, d - 2, d - 1]

arraysize s, b

for i = 0 to s - 1

print b[i], " : ", b[i] * -1

next i

end</syntaxhighlight>
{{out| Output}}<pre>
-1234567 : 1234567
-1234566 : 1234566
-2 : 2
-1 : 1
0 : 0
1 : -1
2 : -2
1234565 : -1234565
1234566 : -1234566
</pre>

=={{header|Delphi}}==
{{works with|Delphi|6.0}}
{{libheader|SysUtils,StdCtrls}}


<syntaxhighlight lang="Delphi">

procedure TwosCompliment(Memo: TMemo);
var N: integer;
begin
N:=123456789;
Memo.Lines.Add(Format('N=%10d $%0.8x',[N,N]));
Memo.Lines.Add('');
Memo.Lines.Add('N:=(N xor $FFFFFFFF)+1');
N:=(N xor $FFFFFFFF)+1;
Memo.Lines.Add('');
Memo.Lines.Add(Format('N=%10d $%0.8x',[N,N]));
end;


</syntaxhighlight>
{{out}}
<pre>
N= 123456789 $075BCD15

N:=(N xor $FFFFFFFF)+1

N=-123456789 $F8A432EB
Elapsed Time: 5.206 ms.
</pre>


=={{header|Forth}}==
{{works with|gforth|0.7.3}}
Forth uses two's complement internally. One can use the 'base' variable to switch from one base to another.
<syntaxhighlight lang="forth">: 2s'complement base @ swap dup negate swap 2 base ! u. u. base ! ;
25 2s'complement</syntaxhighlight>

{{out}}
<pre>11001 1111111111111111111111111111111111111111111111111111111111100111 ok
</pre>



=={{header|FreeBASIC}}==
=={{header|FreeBASIC}}==
In FreeBASIC as in C, if a number n is any integer type, then -n is the two's complement of n, with type preserved.
In FreeBASIC as in C, if a number n is any integer type, then -n is the two's complement of n, with type preserved.
<lang freebasic>Dim As Integer d1 = 2147483648, d2 = 2147483646
<syntaxhighlight lang="freebasic">Dim As Integer d1 = 2147483648, d2 = 2147483646
Dim As Integer b(1 To ...) = {-d1, -d1+1, -2, -1, 0, 1, 2, d1-2, d1-1}
Dim As Integer b(1 To ...) = {-d1, -d1+1, -2, -1, 0, 1, 2, d1-2, d1-1}
For i As Integer = 1 To Ubound(b)
For i As Integer = 1 To Ubound(b)
Print b(i); " -> "; -b(i)
Print b(i); " -> "; -b(i)
Next i
Next i
Sleep</lang>
Sleep</syntaxhighlight>
{{out}}
{{out}}
<pre>0000000000000011 -> 1111111111111101</pre>
<pre>0000000000000011 -> 1111111111111101</pre>


=== inline assembly ===
=== inline assembly ===
<lang freebasic>Dim As Integer a = &b000011
<syntaxhighlight lang="freebasic">Dim As Integer a = &b000011
Dim As Integer a2c, l
Dim As Integer a2c, l
#ifdef __FB_64BIT__
#ifdef __FB_64BIT__
Line 111: Line 244:


Print Bin(a, l); " -> "; Bin(a2c, l)
Print Bin(a, l); " -> "; Bin(a2c, l)
Sleep</lang>
Sleep</syntaxhighlight>
{{out}}
{{out}}
<pre>-2147483648 -> 2147483648
<pre>-2147483648 -> 2147483648
Line 125: Line 258:
=={{header|J}}==
=={{header|J}}==
J uses twos complement natively:
J uses twos complement natively:
<lang J> -3
<syntaxhighlight lang="j"> -3
_3</lang>
_3</syntaxhighlight>


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


<lang J> (8#2)#:3
<syntaxhighlight lang="j"> (8#2)#:3
0 0 0 0 0 0 1 1
0 0 0 0 0 0 1 1
(8#2)#:-3
(8#2)#:-3
1 1 1 1 1 1 0 1</lang>
1 1 1 1 1 1 0 1</syntaxhighlight>

=={{header|Java}}==
In Java the two's complement of an integer 'n' is its arithmetic negation '-n'.

The two's complement of an integer 'n' can also be calculated by adding 1 to its bitwise complement '~n'.
<syntaxhighlight lang="java">
import java.util.List;

public final class TwosComplement {

public static void main(String[] args) {
List<Integer> examples = List.of( 0, 1, -1, 42 );
System.out.println(String.format("%9s%12s%24s%34s", "decimal", "hex", "binary", "two's complement"));
System.out.println(
String.format("%6s%12s%24s%32s", "-----------", "--------", "----------", "----------------"));
for ( int example : examples ) {
System.out.println(String.format("%5d%18s%36s%13d",
example, toHex(example), toBinary(example), twosComplement(example)));
}
}
private static String toHex(int number) {
return String.format("%8s", Integer.toHexString(number).toUpperCase()).replace(" ", "0");
}
private static String toBinary(int number) {
return String.format("%32s", Integer.toBinaryString(number)).replace(" ", "0");
}
private static int twosComplement(int number) {
return ~number + 1;
}

}
</syntaxhighlight>
{{ out }}
<pre>
decimal hex binary two's complement
----------- -------- ---------- ----------------
0 00000000 00000000000000000000000000000000 0
1 00000001 00000000000000000000000000000001 -1
-1 FFFFFFFF 11111111111111111111111111111111 1
42 0000002A 00000000000000000000000000101010 -42
</pre>

=={{header|Jakt}}==
<syntaxhighlight lang="jakt">
fn main() {
let n = 0xabcdeabcdeu64
println("{:064b}", n)
println("{:064b}", ~n + 1)
println("{:064b}", -n) // Same result
}
</syntaxhighlight>
{{out}}
<pre>
0000000000000000000000001010101111001101111010101011110011011110
1111111111111111111111110101010000110010000101010100001100100010
1111111111111111111111110101010000110010000101010100001100100010
</pre>


=={{header|Julia}}==
=={{header|Julia}}==
In Julia as in C, if a number n is any integer type, then -n is the two's complement of n, with type preserved. This is true even if n is unsigned.
In Julia as in C, if a number n is any integer type, then -n is the two's complement of n, with type preserved. This is true even if n is unsigned.
=={{header|M2000 Interpreter}}==


<syntaxhighlight lang="m2000 interpreter">
Module Complement2{
// we use binary.and to get a number in range of byte 0 to 255
byte k, v
v=random(1, 255) ' there is no two's complement for zero
z=binary.and(binary.not(v)+1, 0xFF)
print v
print z
print z=255-v+1 // z is type of byte always positive
print sint(z+0xFFFFFF00)=-v // using 4bytes, we add unsinged 0xFFFFFF00
}
Complement2
Complement2
</syntaxhighlight>
{{out}}
<pre>
2
254
True
True
208
48
True
True
</pre>

=={{header|Nim}}==
We define a function to compute the two’s complement by taking the logical complement and adding one. As Nim uses the native complement of the computer, which is two’s complement, the result should be equal to the arithmetic negation.

<syntaxhighlight lang="Nim">import std/[strformat, strutils]

func twosComplement[T: SomeSignedInt](n: T): T =
## Compute the two's complement of "n".
not n + 1

echo &"""{"n":^15}{"2's complement":^15}{"-n":^15}"""
for n in [0i32, 1i32, -1i32]:
echo &"{n.toHex:^15}{twosComplement(n).toHex:^15}{(-n).toHex:^15}"
for n in [-50i8, 50i8]:
echo &"{n.toHex:^15}{twosComplement(n).toHex:^15}{(-n).toHex:^15}"
</syntaxhighlight>

{{out}}
<pre> n 2's complement -n
──────── ────────────── ────────
00000000 00000000 00000000
00000001 FFFFFFFF FFFFFFFF
FFFFFFFF 00000001 00000001
CE 32 32
32 CE CE
</pre>

=={{header|Perl}}==
<syntaxhighlight lang="perl" line>use strict;
use warnings;

for ( -2**31, -2**31+1, -2, -1, 0, 1, 2, 2**31-2, 2**31-1 ) {
printf "$_ -> %d\n", $_ == 0 ? 0 : ~$_+1
}</syntaxhighlight>
Output is the same as the Wren entry.


=={{header|Phix}}==
=={{header|Phix}}==
=== inline assembly ===
=== inline assembly ===
<!--<lang Phix>-->
<!--<syntaxhighlight lang="phix">-->
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span>
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0b000011</span><span style="color: #0000FF;">,</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0b000011</span><span style="color: #0000FF;">,</span>
Line 155: Line 413:
}
}
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%032b -&gt; %032b\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a2c</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%032b -&gt; %032b\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a2c</span><span style="color: #0000FF;">})</span>
<!--</lang>-->
<!--</syntaxhighlight>-->
{{out}}
{{out}}
<pre>
<pre>
Line 161: Line 419:
</pre>
</pre>
=== normal hll ===
=== normal hll ===
<!--<lang Phix>(phixonline)-->
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0b000011</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0b000011</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%032b -&gt; %032b\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">a</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%032b -&gt; %032b\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">a</span><span style="color: #0000FF;">})</span>
<!--</lang>-->
<!--</syntaxhighlight>-->
Same output (naturally the rhs is twice as long under 64 bit, in both cases)
Same output (naturally the rhs is twice as long under 64 bit, in both cases)


Line 172: Line 430:
<br>
<br>
Even though the original PL/M 8080 compiler only handles unsigned integers, <code>-A</code> two's complements <code>A</code>.
Even though the original PL/M 8080 compiler only handles unsigned integers, <code>-A</code> two's complements <code>A</code>.
<lang pli>100H: /* TWO'S COMPLEMENT *?
<syntaxhighlight lang="pli">100H: /* TWO'S COMPLEMENT *?


/* CP/M BDOS SYSTEM CALL */
/* CP/M BDOS SYSTEM CALL */
Line 197: Line 455:
CALL PR$NL;
CALL PR$NL;


EOF</lang>
EOF</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
01 FF
01 FF
</pre>
</pre>

=={{header|Python}}==
<syntaxhighlight lang="python">-n</syntaxhighlight>
or
<syntaxhighlight lang="python">~n+1</syntaxhighlight>

=={{header|Quackery}}==

Ways of calculating the two's complement of an integer in Quackery include <code>negate</code>, <code>~ 1+</code>, <code>-1 *</code>, and <code>0 swap -</code>.

These are demonstrated as a dialogue in the Quackery shell.

<pre>/O> 37 negate
...

Stack: -37

/O> negate
...

Stack: 37

/O> ~ 1+
...

Stack: -37

/O> ~ 1+
...

Stack: 37

/O> -1 *
...

Stack: -37

/O> -1 *
...

Stack: 37

/O> 0 swap -
...

Stack: -37

/O> 0 swap -
...

Stack: 37

/O> </pre>


=={{header|Raku}}==
=={{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 use fixed size integers.
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 use 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].
There is a module available from the Raku ecosystem that provides fixed size integer support, named (appropriately enough.) [https://raku.land/zef: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.
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.
Line 212: Line 523:
Here we'll demonstrate twos complement on a 57 bit integer.
Here we'll demonstrate twos complement on a 57 bit integer.


<lang perl6>use FixedInt;
<syntaxhighlight lang="raku" line>use FixedInt;


# Instantiate a new 57(!) bit fixed size integer
# Instantiate a new 57(!) bit fixed size integer
Line 225: Line 536:


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

=={{header|RPL}}==
RPL can handle integers whose size can be set from 1 to 64 bits. For this task, a 8-bit size is selected with <code>STWS</code>.
RPL considers 'true' integers (i.e. declared by the prefix <code>#</code>) to be positive, so the two's complement can not be done by the <code>NEG</code> instruction.
8 STWS BIN
#3d NOT 1 +
{{out}}
<pre>
1: #11111101b
</pre>
=={{header|Ruby}}==
Ruby integers have a built-in 'one-complement'method: '''~''', which flips all bits. Adding 1 leads to a negative integer:
<syntaxhighlight lang="ruby">~42 + 1 # => -42
</syntaxhighlight>


=={{header|Wren}}==
=={{header|Wren}}==
Line 236: Line 561:


This is illustrated by running the following code:
This is illustrated by running the following code:
<lang ecmascript>var a = 0
<syntaxhighlight lang="wren">var a = 0
a = -a
a = -a
System.print(a) // -0</lang>
System.print(a) // -0</syntaxhighlight>
which produces 'negative zero' rather than just 'zero'.
which produces 'negative zero' rather than just 'zero'.


Line 245: Line 570:
We can therefore emulate how two's complement works on ''signed'' 32 bit integers by using the bitwise complement operator '''~''' to flip the bits as follows:
We can therefore emulate how two's complement works on ''signed'' 32 bit integers by using the bitwise complement operator '''~''' to flip the bits as follows:


<lang ecmascript>var pow32 = 2.pow(32)
<syntaxhighlight lang="wren">var pow32 = 2.pow(32)
var pow31 = 2.pow(31)
var pow31 = 2.pow(31)
var bs = [-pow31, -pow31+1, -2, -1, 0, 1, 2, pow31-2, pow31-1]
var bs = [-pow31, -pow31+1, -2, -1, 0, 1, 2, pow31-2, pow31-1]
Line 252: Line 577:
if (b2 > pow31) b2 = b2 - pow32
if (b2 > pow31) b2 = b2 - pow32
System.print("%(b) -> %(b2)")
System.print("%(b) -> %(b2)")
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 268: Line 593:


=={{header|XPL0}}==
=={{header|XPL0}}==
<lang XPL0>int I; char C;
<syntaxhighlight lang="xpl0">int I; char C;
[I:= 123;
[I:= 123;
I:= (~I) + 1;
I:= (~I) + 1;
Line 275: Line 600:
C:= ~(C-1);
C:= ~(C-1);
IntOut(0, C); CrLf(0);
IntOut(0, C); CrLf(0);
]</lang>
]</syntaxhighlight>


{{out}}
{{out}}
Line 288: Line 613:
'''Zilog Z80'''
'''Zilog Z80'''


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


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


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

Latest revision as of 16:03, 14 February 2024

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

LDA #%01010101
EOR #255
CLC
ADC #1 ;result: #%10101011

16-bit

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

68000 Assembly

MOVE.L #3,D0
NEG.L D0 ;D0 = #$FFFFFFFD

8086 Assembly

mov al,17
neg al ;8-bit
mov bx,4C00h
neg bx ;16-bit

ALGOL 68

Algol 68 uses whatever representation the hardware the program is running on uses, which is almost certainly two's complement. So, as in C and most other languages, -a two's complements a. Using Algol 68's bit manipulation facilities, we can explicitely two's complement a positive integer, as shown in this example.
Note: BIN a converts a to a BITS (bit-string) value, the NOT operator will flip the bits and the ABS operator will convert back to an integer, so 1 + ABS NOT BIN a is a long-winded alternative to -a. Note in Algol 68, the BIN operator cannot be applied to negative integers, so 1 + ABS NOT BIN -3 won't work.

BEGIN
    INT a := 3;
    print( ( -a, " ", 1 + ABS NOT BIN a, newline ) )
END
Output:
-3 -3

ALGOL W

Translation of: ALGOL 68
begin
    integer a;
    a := 3;
    write( i_w := 1, s_w := 1, -a, 1 + number( not bitstring( a ) ) )
end.
Output:
-3 -3

ARM Assembly

MOV R0,#0x0000000F
MOV R1,#1
MVN R0,R0    ;flips the bits of R0, R0 = 0xFFFFFFF0
ADD R0,R0,R1 ;R0 = 0xFFFFFFF1

C

int a = 3;
a = -a;

C++

In C++ the two's complement of an integer 'n' is its arithmetic negation '-n'.

The two's complement of an integer 'n' can also be calculated by adding 1 to its bitwise complement '~n'.

#include <cstdint>
#include <iostream>
#include <iomanip>
#include <vector>
#include <bitset>

std::string to_hex(const int32_t number) {
    std::stringstream stream;
    stream << std::setfill('0') << std::setw(8) << std::hex << number;
    return stream.str();
}

std::string to_binary(const int32_t number) {
	std::stringstream stream;
	stream << std::bitset<16>(number);
	return stream.str();
}

int32_t twos_complement(const int32_t number) {
	return ~number + 1;
}

std::string to_upper_case(std::string str) {
	for ( char& ch : str ) {
		ch = toupper(ch);
	}
	return str;
}

int main() {
	std::vector<int32_t> examples = { 0, 1, -1, 42 };

	std::cout << std::setw(9) << "decimal" << std::setw(12) << "hex"
			  << std::setw(17) << "binary" << std::setw(25) << "two's complement" << std::endl;
	std::cout << std::setw(6) << "-----------" << std::setw(12) << "--------"
			  << std::setw(20) << "----------------" << std::setw(20) << "----------------" << std::endl;

	for ( const int32_t& example : examples ) {
		std::cout << std::setw(6) << example << std::setw(17) << to_upper_case(to_hex(example))
				  << std::setw(20) << to_binary(example) << std::setw(13) << twos_complement(example) << std::endl;
	}
}
Output:
  decimal         hex           binary         two's complement
-----------    --------    ----------------    ----------------
     0         00000000    0000000000000000            0
     1         00000001    0000000000000001           -1
    -1         FFFFFFFF    1111111111111111            1
    42         0000002A    0000000000101010          -42

Craft Basic

let d = 1234567

dim b[d * -1, d * -1 + 1, -2, -1, 0, 1, 2, d - 2, d - 1]

arraysize s, b

for i = 0 to s - 1

	print b[i], " : ", b[i] * -1

next i

end
Output:

-1234567 : 1234567 -1234566 : 1234566 -2 : 2 -1 : 1 0 : 0 1 : -1 2 : -2 1234565 : -1234565 1234566 : -1234566

Delphi

Works with: Delphi version 6.0


procedure TwosCompliment(Memo: TMemo);
var N: integer;
begin
N:=123456789;
Memo.Lines.Add(Format('N=%10d $%0.8x',[N,N]));
Memo.Lines.Add('');
Memo.Lines.Add('N:=(N xor $FFFFFFFF)+1');
N:=(N xor $FFFFFFFF)+1;
Memo.Lines.Add('');
Memo.Lines.Add(Format('N=%10d $%0.8x',[N,N]));
end;
Output:
N= 123456789 $075BCD15

N:=(N xor $FFFFFFFF)+1

N=-123456789 $F8A432EB
Elapsed Time: 5.206 ms.


Forth

Works with: gforth version 0.7.3

Forth uses two's complement internally. One can use the 'base' variable to switch from one base to another.

: 2s'complement base @ swap dup negate swap 2 base ! u. u. base ! ;
25 2s'complement
Output:
11001 1111111111111111111111111111111111111111111111111111111111100111  ok


FreeBASIC

In FreeBASIC as in C, if a number n is any integer type, then -n is the two's complement of n, with type preserved.

Dim As Integer d1 = 2147483648, d2 = 2147483646
Dim As Integer b(1 To ...) = {-d1, -d1+1, -2, -1, 0, 1, 2, d1-2, d1-1}
For i As Integer = 1 To Ubound(b)
    Print b(i); " -> "; -b(i)
Next i
Sleep
Output:
0000000000000011 -> 1111111111111101

inline assembly

Dim As Integer a = &b000011
Dim As Integer a2c, l
#ifdef __FB_64BIT__
    l = 16
    Asm
        mov rax, [a]
        neg rax
        mov [a2c], rax
    End Asm
#else
    l = 8
    Asm
        mov eax, [a]
        neg eax
        mov [a2c], eax
    End Asm
#endif

Print Bin(a, l); " -> "; Bin(a2c, l)
Sleep
Output:
-2147483648 ->  2147483648
-2147483647 ->  2147483647
-2 ->  2
-1 ->  1
 0 ->  0
 1 -> -1
 2 -> -2
 2147483646 -> -2147483646
 2147483647 -> -2147483647

J

J uses twos complement natively:

   -3
_3

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

   (8#2)#:3
0 0 0 0 0 0 1 1
   (8#2)#:-3
1 1 1 1 1 1 0 1

Java

In Java the two's complement of an integer 'n' is its arithmetic negation '-n'.

The two's complement of an integer 'n' can also be calculated by adding 1 to its bitwise complement '~n'.

import java.util.List;

public final class TwosComplement {

	public static void main(String[] args) {
		List<Integer> examples = List.of( 0, 1, -1, 42 );
		
		System.out.println(String.format("%9s%12s%24s%34s", "decimal", "hex", "binary", "two's complement"));
		System.out.println(
            String.format("%6s%12s%24s%32s", "-----------", "--------", "----------", "----------------"));
		
		for ( int example : examples ) {
			System.out.println(String.format("%5d%18s%36s%13d",
                example, toHex(example), toBinary(example), twosComplement(example)));
		}
	}
	
	private static String toHex(int number) {
		return String.format("%8s", Integer.toHexString(number).toUpperCase()).replace(" ", "0");
	}
	
	private static String toBinary(int number) {
		return String.format("%32s", Integer.toBinaryString(number)).replace(" ", "0");
	}
	
	private static int twosComplement(int number) {
		return ~number + 1;
	}

}
Output:
  decimal         hex                  binary                  two's complement
-----------    --------              ----------                ----------------
    0          00000000    00000000000000000000000000000000            0
    1          00000001    00000000000000000000000000000001           -1
   -1          FFFFFFFF    11111111111111111111111111111111            1
   42          0000002A    00000000000000000000000000101010          -42

Jakt

fn main() {
    let n = 0xabcdeabcdeu64
    println("{:064b}", n)
    println("{:064b}", ~n + 1)
    println("{:064b}", -n) // Same result
}
Output:
0000000000000000000000001010101111001101111010101011110011011110
1111111111111111111111110101010000110010000101010100001100100010
1111111111111111111111110101010000110010000101010100001100100010

Julia

In Julia as in C, if a number n is any integer type, then -n is the two's complement of n, with type preserved. This is true even if n is unsigned.

M2000 Interpreter

Module Complement2{
	// we use binary.and to get a number in range of byte 0 to 255
	byte k, v
	v=random(1, 255)  ' there is no two's complement for zero
	z=binary.and(binary.not(v)+1, 0xFF)
	print v
	print z
	print z=255-v+1 // z is type of byte always positive
	print sint(z+0xFFFFFF00)=-v  // using 4bytes, we add unsinged 0xFFFFFF00
}
Complement2
Complement2
Output:
     2
   254
  True
  True
   208
    48
  True
  True

Nim

We define a function to compute the two’s complement by taking the logical complement and adding one. As Nim uses the native complement of the computer, which is two’s complement, the result should be equal to the arithmetic negation.

import std/[strformat, strutils]

func twosComplement[T: SomeSignedInt](n: T): T =
  ## Compute the two's complement of "n".
  not n + 1

echo &"""{"n":^15}{"2's complement":^15}{"-n":^15}"""
for n in [0i32, 1i32, -1i32]:
  echo &"{n.toHex:^15}{twosComplement(n).toHex:^15}{(-n).toHex:^15}"
for n in [-50i8, 50i8]:
  echo &"{n.toHex:^15}{twosComplement(n).toHex:^15}{(-n).toHex:^15}"
Output:
       n       2's complement       -n       
   ────────    ──────────────    ────────
   00000000       00000000       00000000    
   00000001       FFFFFFFF       FFFFFFFF    
   FFFFFFFF       00000001       00000001    
      CE             32             32       
      32             CE             CE   

Perl

use strict;
use warnings;

for ( -2**31, -2**31+1, -2, -1, 0, 1, 2, 2**31-2, 2**31-1 ) {
   printf "$_ -> %d\n", $_ == 0 ? 0 : ~$_+1
}

Output is the same as the Wren entry.

Phix

inline assembly

without js
integer a = 0b000011,
        a2c
#ilASM{
    [32]
        mov eax,[a]
        neg eax
        mov [a2c],eax
    [64]
        mov rax,[a]
        neg rax
        mov [a2c],rax
     }
printf(1,"%032b -> %032b\n",{a,a2c})
Output:
00000000000000000000000000000011 -> 11111111111111111111111111111101

normal hll

with javascript_semantics
integer a = 0b000011
printf(1,"%032b -> %032b\n",{a,-a})

Same output (naturally the rhs is twice as long under 64 bit, in both cases)

PL/M

Works with: 8080 PL/M Compiler

... under CP/M (or an emulator)


Even though the original PL/M 8080 compiler only handles unsigned integers, -A two's complements A.

100H: /* TWO'S COMPLEMENT                                                   *?

   /* CP/M BDOS SYSTEM CALL */
   BDOS: PROCEDURE( FN, ARG ); DECLARE FN BYTE, ARG ADDRESS; GOTO 5;END;
   /* CONSOLE OUTPUT ROUTINES */
   PR$CHAR:   PROCEDURE( C ); DECLARE C BYTE;    CALL BDOS( 2, C ); END;
   PR$NL:     PROCEDURE; CALL PR$CHAR( 0DH ); CALL PR$CHAR( 0AH );  END;
   PR$HEX: PROCEDURE( B ); /* PRINTS B AS A 2 DIGIT HEX NUMBER */
      DECLARE B BYTE;
      DECLARE D BYTE;
      IF ( D := SHR( B, 4 ) ) > 9 THEN CALL PR$CHAR( ( D - 10 ) + 'A' );
                                  ELSE CALL PR$CHAR(     D      + '0' );
      IF ( D := B AND 0FH   ) > 9 THEN CALL PR$CHAR( ( D - 10 ) + 'A' );
                                  ELSE CALL PR$CHAR(     D      + '0' );
   END PR$HEX ;

   DECLARE A  BYTE;

   A = 1;
   CALL PR$HEX( A );
   CALL PR$CHAR( ' ' );
   A = -A;
   CALL PR$HEX( A );
   CALL PR$NL;

EOF
Output:
01 FF

Python

-n

or

~n+1

Quackery

Ways of calculating the two's complement of an integer in Quackery include negate, ~ 1+, -1 *, and 0 swap -.

These are demonstrated as a dialogue in the Quackery shell.

/O> 37 negate
... 

Stack: -37 

/O> negate
... 

Stack: 37 

/O> ~ 1+
... 

Stack: -37 

/O> ~ 1+
... 

Stack: 37 

/O> -1 *
... 

Stack: -37 

/O> -1 *
... 

Stack: 37 

/O> 0 swap -
... 

Stack: -37 

/O> 0 swap -
... 

Stack: 37 

/O> 

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 use 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.

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
Output:
144114427045277101
0b111111111111111110100111011001111000010101110110110101101
761030578771
0b000000000000000001011000100110000111101010001001001010011

RPL

RPL can handle integers whose size can be set from 1 to 64 bits. For this task, a 8-bit size is selected with STWS. RPL considers 'true' integers (i.e. declared by the prefix #) to be positive, so the two's complement can not be done by the NEG instruction.

8 STWS BIN
#3d NOT 1 +
Output:
1: #11111101b

Ruby

Ruby integers have a built-in 'one-complement'method: ~, which flips all bits. Adding 1 leads to a negative integer:

~42 + 1 # => -42

Wren

Strictly speaking, Wren doesn't have integers. Instead all numbers are 'IEEE 754' 64 bit floating point values (their underlying C type being double) and negative numbers are therefore represented using the offset binary method rather than two's complement.

This is illustrated by running the following code:

var a = 0
a = -a
System.print(a) // -0

which produces 'negative zero' rather than just 'zero'.

However, when using the bitwise operators, Wren's VM emulates the corresponding operation in C by first converting the operands to unsigned 32 bit values, performing the operation and then converting the result back to a double.

We can therefore emulate how two's complement works on signed 32 bit integers by using the bitwise complement operator ~ to flip the bits as follows:

var pow32 = 2.pow(32)
var pow31 = 2.pow(31)
var bs = [-pow31, -pow31+1, -2, -1, 0, 1, 2, pow31-2, pow31-1]
for (b in bs) {
    var b2 = ~b + 1
    if (b2 > pow31) b2 = b2 - pow32
    System.print("%(b) -> %(b2)")
}
Output:
-2147483648 -> 2147483648
-2147483647 -> 2147483647
-2 -> 2
-1 -> 1
0 -> 0
1 -> -1
2 -> -2
2147483646 -> -2147483646
2147483647 -> -2147483647

XPL0

int I;  char C;
[I:= 123;
I:= (~I) + 1;
IntOut(0, I);  CrLf(0);
C:= -123;
C:= ~(C-1);
IntOut(0, C);  CrLf(0);
]
Output:
-123
123

Z80 Assembly

8-Bit

Zilog Z80

ld a,%00001111
neg ;returns %11110001 in a

Game Boy

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

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.

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