110円にならない税込み価格
冬の札幌の気温は -8℃ になることがあります。コンビニの100円のおにぎりは、税込みで100 × 1.1 円です。
前回、1バイトは0から255を表しました。マイナスの記号も小数点もありませんでした。では、コンピュータは0より小さい数や小数をどう記録するのでしょうか。
このレッスンのゴール
メモ
負の数と小数をビットで表すことができる。
キーワード
| ことば | いみ |
|---|---|
| 2の補数 | 負の整数をビットで表す、ふつうのやり方 |
| 最上位ビット | いちばん左の、重みがいちばん大きいビット |
| オーバーフロー | 答えが大きすぎて、決まったビット数に入らないこと |
| 固定小数点 | 小数点の位置がいつも同じ場所にある数 |
| 浮動小数点 | 数字と、小数点を動かす指数を分けて記録する数 |
| 丸め誤差 | 値をぴったり記録できないために出る小さなずれ |
学生が入力するセルは、このプレビューでは空白です。
始める前に
メモ
上のバーの Start the lab を押し、マシンが動き出すまで待ってください。Run ボタンは、順番にコマンドをマシンのターミナルに入力します。
いちばん上のビットはマイナス
2の補数では、1バイトのいちばん左のビットの重みを 128 ではなく -128 にします。残りの7ビットは、ふつうの重みのままです。
だから、0で始まるバイトは0か正の数です。1で始まるバイトは負の数です。1バイトで表せるのは -128 から 127 になります。数の種類は、前と同じ256個です。
例: 同じ1バイトの2つの読み方
| ビット | 0から255として読む | 2の補数として読む | 計算 |
|---|---|---|---|
| 00000101 | 5 | 5 | 4 + 1 |
| 01111111 | 127 | 127 | 64 + 32 + 16 + 8 + 4 + 2 + 1 |
| 10000000 | 128 | -128 | -128 |
| 11111100 | 252 | -4 | -128 + 64 + 32 + 16 + 8 + 4 |
| 11111111 | 255 | -1 | -128 + 127 |
学生が入力するセルは、このプレビューでは空白です。
ビットを反転して1を足す
負の数を早く書く方法があります。まず、正の数を8ビットで書きます。次に、すべてのビットを反転します。0は1に、1は0にします。最後に1を足します。
同じ手順で、負の数を正の数にもどすこともできます。
例: -4 を書く
| 手順 | ビット |
|---|---|
| 4を書く | 00000100 |
| すべて反転する | 11111011 |
| 1を足す | 11111100 |
学生が入力するセルは、このプレビューでは空白です。
arch フォルダへ移る
cd ~/archここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
-4 を返す C プログラムを書く
printf 'int main(void) { return -4; }\n' > minus.cここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
コンパイルする
gcc minus.c -o minusここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
実行する
./minusここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
返した値をシェルに聞く
echo $?ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
よくある間違い
注意
ビットそのものが「負の数」だと言っている、と考える人がよくいます。そうではありません。プログラムは -4 を 11111100 として返しました。シェルはこれを0から255として読むので、252 と表示しました。同じビットが、読み方しだいで -4 にも 252 にもなります。
固定小数点は小数点を動かさない
税率の計算は、小数で書くとまちがえやすいです。そこで多くのプログラムは、100 × 110 ÷ 100 のように整数だけで計算します。整数の計算は正確です。
2進数でも、小数点の場所を決めておけます。小数点の右のけたの重みは、2分の1、4分の1、8分の1と半分になります。
例: 5.75 を固定小数点で表す
| けたの重み | 8 | 4 | 2 | 1 | . | 1/2 | 1/4 | 1/8 | 1/16 |
|---|---|---|---|---|---|---|---|---|---|
| ビット | 0 | 1 | 0 | 1 | . | 1 | 1 | 0 | 0 |
| 足す値 | 0 | 4 | 0 | 1 | . | 1/2 | 1/4 | 0 | 0 |
学生が入力するセルは、このプレビューでは空白です。
浮動小数点は小数点を動かす
固定小数点では、とても大きい数ととても小さい数を同じビットに入れられません。浮動小数点は、数字と指数を分けて記録します。5.75 を 0.575 × 10 と書くようなものです。
0.1 や 1.1 のような多くの小数は、2進数ではぴったり書けません。とても近い値として記録されます。
100に1.1をかける
python3 -c "print(100 * 1.1)"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
1.1の本当の中身を見る
python3 -c "print(format(1.1, '.20f'))"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
さらに挑戦: 16ビットの得点
あるゲームは、プレイヤーの得点を16ビットの2の補数で記録しています。記録できるいちばん大きい得点と、いちばん小さい得点はいくつですか。
1バイトと同じく、いちばん上のビットの重みはマイナスです。いちばん大きい得点にさらに1点入ると、どうなるかも考えてください。