2進数における負の数
これまで私たちは、正の整数とそのマシン上での表現方法について扱ってきました。しかし、時には負の数を扱う必要もあります。コンピュータでは、それらをどのように表現しているのでしょうか?
たとえば、1 は 2進数で
0001
、6 は 0110
のように表現されます。また、0 は全ビットが 0 の 0000
で表されます。ここで、負の数を格納するための「特別な」ビットを用意し、それが 1 なら負の数、0 なら正の数を表すようにすると、負の値も扱えます。実際に、多くのコンピュータではこの方法で負の数を扱っており、最も左のビットが 1 のときに負の数、0 のときに正の数になっています。しかし、単に先頭ビットを 1 にするだけでは不十分です。10進数(4、5、10、311など)では、正と負の数がお互い打ち消し合って 0 になる性質があります。つまり 6 と -6 を足すと 0 になるわけですが、2進数でもこの性質は維持されます。6 と -6 を 2進数で足しても 0 となるように表現しなければなりません。
もし 4 ビットで数を表し、さらに符号ビットを 1 つ加えた合計 5 ビットで扱うとしましょう。すると、6 は
00110
、0 は 00000
となります。-6 の 2進数表現は、6 と足し合わせたときに 0 になるよう、6 のビットを反転させたものに相当します。結論として -6 は 11010
となり、00110
と 11010
を足すと 00000
になります。プラスとマイナスを 2進数で切り替えるには、ビットをすべて反転させてから 1 を加えるという簡単なトリックを使えます。
x = 6 # 00110
x = ~x + 1 # すべてのビットを反転して1を加える => -6
x = ~x + 1 # すべてのビットを反転して1を加える => 6
z = 0 # 00000
z = ~z + 1 # ビットを反転して+1 => 0
z = ~z + 1 # ビットを反転して+1 => 0
z = ~z # -1 (バイナリ表現ではすべて1)
z = ~z # 0 (バイナリ表現ではすべて0)
なお、2進数での加算は、10進数の加算と同様に下位ビットから上位ビットに向かって桁上がりを考慮しながら行われます。
コンピュータが実際に数を保存する方法は、言語や実装によって異なります。たとえば C++ や Java などでは、異なる範囲の整数を扱うために異なる型があります。
int
型は 32 ビットを使い、31 ビットで数値、先頭ビットで符号を表現します。つまり、-2,147,483,648
($-2^{31}$) から 2,147,483,647
($2^{31}-1$) までの値を表すことができます。ここで、正の範囲が 1 つだけ少なくなるのは、先頭ビットが 0 の場合に最初の数として 0(すべて 0 のビット列)が含まれるためです。 チャレンジ
「7 の魔法の国」では、あらゆるものが 7 にまつわる仕様になっています。この国では、2進数を 77 ビットで(正も負も)保管するシステムを開発しました。
与えられたビット列
b
が表す数に対して、その負の値を求め、77 ビットで表すプログラムを書いてください。 Input
入力は、1 行のビット列
b
(長さ 1 以上 77 以下)です。これは正の数にも負の数にもなりえます。 Output
出力は、77 ビット長で
-b
を表すビット列を 1 行に出力すること。 Examples
Input | Output |
1 | 11111111111111111111111111111111111111111111111111111111111111111111111111111 |
11111111111111111111111111111111111111111111111111111111111111111111111111111 | 00000000000000000000000000000000000000000000000000000000000000000000000000001 |
Constraints
Time limit: 2 seconds
Memory limit: 512 MB
Output limit: 1 MB