コンピュータ内の整数表現

正の整数の表現

4ビットと8ビットのコンピュータが内部に持つデータを変化させ、それを正の整数として見た時に2進法と10進法でどんな数になるかを観察します。

データは0,1の組み合わせですが、とりあえず2進法整数として[+1]ボタンで1増え、[-1]で減り、[clear]で0になるようにしてあります。

4ビットのとき

4ビットなら次のようになります。

内部表現 2進表記 10進表記
0 0 0 0 0 0

4ビットを素直に2進数と解釈すると、0 から 15 まで表現できます。

15は 1111(2)で、さらに加えると 10000(2)になるはずですが、4ビットに入りきらないので 0 になってしまいます。

8ビットのとき

8ビットなら次のようになります。

内部表現 2進表記 10進表記
0 0 0 0 0 0 0 0 0 0

8ビットを素直に2進数と解釈すると、0 から 255 まで表現できます。

255は 11111111(2)で、さらに加えると 100000000(2)になるはずですが、8ビットに入りきらないので 0 になってしまいます。

解説

コンピュータのCPUにはレジスタと呼ばれる装置があります。64ビットのCPUは1つのレジスタが64ビットの0,1の並びを記憶し、64ビットをひとまとめに計算します。0,1のパターンをそのまま2進法の数とみなせば、正の整数を表現できます。

64ビットはちょっと多過ぎますので、4ビットと、8ビットの場合で様子を観察しました。

内部表現がレジスタの内容です。2進表記と10進表記はレジスタの内容を、それぞれ2進法と10進法で解釈したものです。

制作意図

レジスタのビット数により表現できる数に上限があります。上限を超えると0に戻ってしまうところを確認するためのものです。

10進法でいうと4桁で表せる最大の数は9999ですが、それに+1すると10000です。4桁しかないので0だけになってしまうのです。CPUの世界ではこれをoverflow(溢れた)といいます。ここでは省略していますが溢れたことを知らせる信号があります。

加えて0から-1すると最大値になります。10000から1引くと9999になることに相当しますが、0から1を引いても9999になるのは疑問かもしれません。CPUのレジスタはそうなるように設計されていて、ここをうまく利用して負の数を表現するというところにつながっていきます。ここでは、様子を「観察」することが大切です。

2進表記は内部表現とほぼ同じになりますが、左の0がなくなりますので、10進と同様に見ることができるように加えました。

プログラムなど

プログラムは4ビットと8ビットを分離できるように独立して作ってあります。

似たようなプログラムである「2進法の繰り上がり」にあったwindow.onload の部分はあえてなくしました。znum4、znum8をグローバル変数として使うのは共通です。

4ビット

javascriptの部分

<script>
var znum4 = 0;
function incnum4(){
   znum4 += 1;
   if (znum4>15){
      znum4 -= 16;
   }
   disp4();
}
function decnum4(){
   if (znum4>0){
      znum4 -= 1;
   }else{
      znum4 = 15;
   }
   disp4();
}
function clrnum4(){
   znum4 = 0;
   disp4();
}
function disp4(){
   var tgt = document.getElementById("reg4");
   var tgttd = tgt.getElementsByTagName("td");
   var bstr = "000" + znum4.toString(2);
   bstr = bstr.substring(bstr.length-4);
   for (var i=0;bstr.length>i;i++){ 
      tgttd[i].firstChild.nodeValue = bstr.substring(i,i+1);
   }
   tgttd[bstr.length].firstChild.nodeValue = znum4.toString(2);
   tgttd[bstr.length+1].firstChild.nodeValue = znum4.toString(10);
}
</script>

[+1]ボタンでincnum4()、[-1]でdecnum4()が呼び出されます。0~15の範囲から出ないようにznum4を増減します。

"000"を加えてsubstringで部分文字列を得ていますが、2進法の数の左を0でうめた4文字とするためです。

znumが 3 の場合、substringで 0011となる様子。substring前のbstr.lengthは5

substring前の文字列番号 0 1 2 3 4
"000"+znum4.toString(2) 0 0 0 1 1
bstr.length-4の位置

znumが 5 の場合、substringで 0101となる様子。substring前のbstr.lengthは6

substring前の文字列番号 0 1 2 3 4 5
"000"+znum4.toString(2) 0 0 0 1 0 1
bstr.length-4の位置

部分文字列は、str.substring(indexStart[, indexEnd])と、str.substr(start[, length])の2種類があり、str.substr(-4)とすると末尾4文字になるはずだが、IEがそうならないので回避策として上記を使っている。

var tgttd = tgt.getElementsByTagName("td");で得られる tgttd は配列になります。

htmlの部分

<table class="reg">
<tr>
<th colspan="4">内部表現</th>
<th>2進表記</th>
<th>10進表記</th>
</tr>
<tr id="reg4">
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td class="num">0</td>
<td class="num">0</td>
</tr>
<tr>
<td class="incdec" colspan="6">
<button type="button" onclick="incnum4()">+1</button>
<button type="button" onclick="decnum4()">-1</button>
<button type="button" onclick="clrnum4()">clear</button>
</td>
</tr>
</table>

css

.reg{ border:none; }
#reg4, #reg8{
  font-size:200%;
  text-align :center;
}
#reg4 td, #reg8 td{
  padding:2px 6px;
}
td.num{
  text-align :right;
}
td.incdec{
  padding-top:0.8em;
  text-align :left;
  border:none;
}
button{
  cursor:pointer;
  min-width:4em;
}

8ビット

javascriptの部分

<script>
/* 8ビット部 */
var znum8 = 0;
function incnum8(){
   if (255>znum8){
      znum8 += 1;
   }else{
      znum8 = 0;
   }
   disp8();
}
function decnum8(){
   if (znum8>0){
      znum8 -= 1;
   }else{
      znum8 = 255;
   }
   disp8();
}
function clrnum8(){
   znum8 = 0;
   disp8();
}
function disp8(n){
   var tgt = document.getElementById("reg8");
   var tgttd = tgt.getElementsByTagName("td");
   var bstr = "0000000" + znum8.toString(2);
   bstr = bstr.substring(bstr.length-8);
   for (var i=0;bstr.length>i;i++){ 
      tgttd[i].firstChild.nodeValue = bstr.substring(i,i+1);
   }
   tgttd[bstr.length].firstChild.nodeValue = znum8.toString(2);
   tgttd[bstr.length+1].firstChild.nodeValue = znum8.toString(10);
}
</script>

htmlの部分

<table class="reg">
<tr>
<th colspan="4">内部表現</th>
<th>2進表記</th>
<th>10進表記</th>
</tr>
<tr id="reg8">
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td class="num">0</td>
<td class="num">0</td>
</tr>
<tr>
<td class="incdec" colspan="10">
<button type="button" onclick="incnum8()">+1</button>
<button type="button" onclick="decnum8()">-1</button>
<button type="button" onclick="clrnum8()">clear</button>
</td>
<td class="incdec" colspan="2"></td>
</tr>
</table>

cssの部分は、4ビットと共通です。