第 2 章 演算方法と演算器#
2.1 数制と符号#
1. 繰り上がりカウント方式と相互変換#
10 進数と R 進数の間の変換
R 進数から 10 進数:
∑i=n−mki×ri
例:二進数を十進数に変換
//二進数から十進数
int bToD(char str[]) {
int sum = 0;
for(int i = 0; str[i] != '\0'; i++) {
sum = sum*2 + (str[i] - '0');
}
return sum;
}
10 進数から R 進数:
- 整数部分:r で割って余りを取る、r は進数の基数
- 小数部分:r を掛けて整数部分を取るコードは以下の通り
//十進数nをk進数の整数に変換
void dToK(int n, int k, char str[]) {
int i = 0;
if (n == 0) {
str[0] = '0';
return;
}
while(n) {
str[i++] =n % k + '0';
n = (n-n % k) / k;
}
i--;
//逆転
for (int j = 0; j < i; j++,i--) {
char t = str[j];
str[j] = str[i];
str[i] = t;
}
}
2. 真値と機械数#
- 真値:一般に書かれる数
- 機械コード:機械内で表現される数、コンピュータ内部での数の正負符号と小数点演算の問題を解決する必要がある。
3. BCD コード#
一桁の十進数の二進数コードの各桁には確定した重みがある。一般に 8421 コードを用い、その 4 つの二進数コードの重みは高い方から 8、4、2、1 である。0000、0001、...、1001 をそれぞれ 0、1、...、9 を表し、各数位内部は二進数の規則を満たし、数位間は十進数の規則を満たすため、この符号化を「二進数で符号化された十進数(binary coded decimal、略して BCD)コード」と呼ぶ。
注意!
BCD コードの取値は 0000 から 1001(すなわち十進数の 0 から 9)までです
時には BCD コードに対して加算または減算を行うと、この範囲外の値が出現することがあり、正しい結果を得るためには手動で調整する必要がある。
コンピュータ内部で BCD コードの算術演算を実装するには、演算結果を修正する必要があり、加算演算の修正規則は次の通りです:
- もし二つの一桁 BCD コードの和が (1001)~2~、すなわち (9)~10~ 以下であれば、修正は必要ない;
例1 ① 1+8 = 9
0 0 0 1
+ 1 0 0 0
——————————
1 0 0 1
修正は不要
- もし和が **(10)~10~ 以上であれば **、加 6 修正を行い、高位に繰り上げる。繰り上げは初回の加算 (例 1 ③) または修正時 (例 1 ②) に発生することがある。
例1 ② 4+9 = 13
0 1 0 0
+ 1 0 0 1
——————————
1 1 0 1
+ 0 1 1 0 修正
——————————
1 0 0 1 1
0001 0011は13~
③ 9+7 = 16
1 0 0 1
+ 0 1 1 1
——————————
1 0 0 0 0
+ 0 1 1 0 修正
——————————
1 0 1 1 0
0001 0110は16~
4. 文字と文字列#
1. 文字と文字列の表現方法#
符号データ:文字情報はデータで表現される、例えばASCIIなど
文字表現方法ASCII: 1 バイトを用いて表現し、下位 7 ビットを符号化に使用し (128)、最上位ビットはチェックビットである。図
文字列の保存方法:主メモリ内の連続した複数のバイトを占有し、各バイトに 1 文字を保存する。
2. 漢字の表現方法#
第 1 水準漢字 3755 字、第 2 水準漢字 3008 字
漢字内コード:漢字情報の保存、交換、検索の機械内コード、2 バイトで構成され、各バイトの高位は 1(英字とは異なる)
漢字字模コード:漢字の字形ドットマトリックス
5. チェックコード(重要)#
推奨動画3Blue1Brown のハミングコード part1、3Blue1Brown のハミングコード part2、非常に面白いです!主にハミングコードについて説明していますが、奇偶チェックコードについても詳細に説明しています。
チェックコード(奇偶チェックコードのみ紹介)
情報伝送と処理の過程で干渉や故障を受けやすく、エラーが発生しやすい。
解決方法#
有効情報にいくつかの冗長情報(チェックビット)を追加する。
x=(x~0~ x~1~.x~n-1~) が n ビットのワードであるとき、偶数チェックビット C は次のように定義される=x~0~ ^ x~1~ ^ x~2~ ^ ... ^x~n-1~、ここで ^ はビットごとの加算を表し、x に偶数個の 1 が含まれている場合のみ C=0となり、そうでない場合は C=1。エラーを検出することはできるが、修正はできない。同様に奇数チェックも定義できる。
奇数チェック:奇数個の 1 が含まれている場合のみ C=0、そうでない場合は C=1
2.2 定点数の表現と演算(重要)#
1. 定点数の表現#
1. 原码表現法#
定点小数 x~n~.x~n-1~x~n-2~…..x~0~、x は真値
\begin{cases}
x, & \text{0 ≤ x < 1 すなわち xは正数} \\
1-x, & \text{-1 < x ≤ 0 すなわち xは負数}
\end{cases}$$
範囲は2^-n^-1~1-2^-n^
例:
x = +0.1001、[x]原 = 0.1001
x = -0.1001、[x]原 = 1-(-0.1001)=1.1001
**定点整数 x~n~x~n-1~x~n-2~…..x~0~**、xは真値
$$[x]_原 =
\begin{cases}
x, & \text{0 ≤ x < }2^n すなわち xは正数\\
2^n-x, & \text{-2}^n<x≤ 0 {すなわちxは負数}
\end{cases}$$
範囲は1-2^n^~2^n^-1
例:
x = +1001、[x]原 = 01001
x = -1001、[x]原 = 2^4^+1001=11001
**正の0と負の0がある!!**
#### 2. 反码表現法
**定義**
- **正数**の表現は原码、補码と同じ。
- **負数**の反码は**符号位が1**、**数値位**は**原码の数値をビットごとに反転**したものである。
- 回路が実装しやすく、フリップフロップの出力には正負の区別がある。
尾数を反転し、反码と補码の違いは末位に1を加えない点であるため、反码の定義を導出できる。
**定点小数 x~n~.x~n-1~x~n-2~…..x~0~**、xは真値
$$[x]_反 =
\begin{cases}
x, & \text{0 ≤ x < 1 すなわち xは正数} \\
(2-2^{-n})+x, & \text{-1 < x ≤ 0 すなわち xは負数}
\end{cases}$$
例:
X1=+0.1011011 , [X1]~反~ =0.1011011
X2= -0.1011011 , [X2]~反~ =1.0100100
**定点整数 x~n~x~n-1~x~n-2~…..x~0~**、xは真値
$$[x]_反 =
\begin{cases}
x, & \text{0 ≤ x < }2^n すなわち xは正数 \\
(2^{n+1}-1)+x, & \text{-2}^n<x≤ 0 {すなわちxは負数}
\end{cases}$$
**反码表現には正の0と負の0がある!!**
#### 3. 補码表現法
**定義**
正数の補码は正数そのものであり、負数の補码は原負数にモジュラスを加えたものである(原負数の符号位を除いて反転し、1を加える)。コンピュータの演算はワード長の制限を受け、モジュラス演算に属する。補码の最大の利点は減算演算を加算演算に変換することである。
**定点小数x~n~x~n-1~x~n-2~…..x~0~、モジュラスは2**
$$[x]_補 =
\begin{cases}
x, & \text{0 ≤ x < 1 すなわち xは正数} \\
2+x, & \text{-1 < x ≤ 0 すなわち xは負数}
\end{cases}$$
例: x= -0.1011、[x]~補~=10+x=10.0000-0.1011=1.0101
y=-0.01111 [y]~補~=10+y=10.00000-0.01111=1.10001
**定点整数xnxn-1xn-2…..x0 、モジュラスは2^n+1^**
$$[x]_補 =
\begin{cases}
x, & \text{2}^n {>x ≥ 0 すなわち xは正数} \\
2^{n+1}+x, & \text{0 ≥ x > -2}^n {すなわちxは負数}
\end{cases}$$
**補码の性質:**
- 高位は正負を示す
- 正数の補码は、尾数は原码と同じ
- 範囲-2^n^~2^n^-1(定点整数)
- **正のゼロと負のゼロの区別はない!!**
#### 4. 移码表現法
階数に使用され、特徴は**移码と補码の尾数は同じで、符号位は逆である**
範囲:-2^n^~2^n^-1
例:真値-1011111
原码は11011111
補码は10100001
反码は10100000
移码は00100001
#### 5. まとめ
- **もしxが正数であれば、[x]~原~ = [x]~補~ = [x]~反~**
- **もしxが負数であれば**、**原码の符号位は1のまま**、整数の各ビットの二進数を反転して反码を得て、反码の符号位は変わらず、反码の数値位の最低位に1を加えて補码を得る。
- **移码と補码の尾数は同じで、符号位は逆である**
### 2. 定点数の演算(重要)
[コンピュータ構成原理 定点演算-シフト、加算、減算、乗算、除算](https://blog.csdn.net/gl620321/article/details/106534016?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-0&spm=1001.2101.3001.4242)
#### 1. 定点数のシフト演算
コンピュータにおけるシフトはデータが小数点に対してシフトされる(左シフトまたは右シフト)、データが移動し、**小数点の位置は変わらない**
##### 符号付き数のシフト
左に1ビットシフト:機械数に対応する真値の絶対値は元の2倍になる
右に1ビットシフト:機械数に対応する真値の絶対値は元の1/2倍になる
シフトの過程で、空いた位置を埋める:
- 負数の数値部分は真値と同じ![ここに画像の説明を挿入](https://img-blog.csdnimg.cn/2021061510432870.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1ODkwNTMz,size_16,color_FFFFFF,t_70)
##### 符号なし数のシフト
- 論理左シフト 低位に0を追加し、高位を捨てる
- 論理右シフト 高位に0を追加し、低位を捨てる
例:
01010011
論理左シフト すべてのビットがシフト操作に参加し、高位の0が捨てられ、最低位に0が追加される:10100110
算術左シフト 最初の0は符号位を示し、この数は正数であり、符号位はシフトに参加せず、シフトされるのは後のデータ00100110
例:
10110010
論理右シフト すべてのビットがシフト操作に参加し、空いた最高位に0が追加され、最低位が捨てられる01011001
算術右シフト 最高位はシフトに参加せず、符号位は負数を示し、右シフトの際に左側の空いた最高位に1が追加され、右側の0が捨てられる11011001
#### 2. 補码加減法
##### 補码加算
公式:$$ [x+y]_補=[x]_補+[y]_補 (mod 2^{n+1}) \\
|x|<(2n-1) , |y|<(2n-1) , |x+y|<(2n-1) $$ 公式は、2^n+1^のモジュラスの意味において、**任意の二数の補码の和はその二数の和の補码に等しい**ことを示す。
証明:
(1)x > 0、y > 0の場合、x+y > 0、正数の原码と補码は同じであるため、[x]~補~+[y]~補~ = x+y = [x+y]~補~
(2)x > 0、y < 0の場合、x+y > 0またはx+y < 0
**[x]~補~= x、[y]~補~ = 2^n+1^+y**
[x]~補~+[y]~補~ = (x+y)+2^n+1^ = [x+y]~補~ (mod 2^n+1^)
(3)x < 0、y > 0の場合、x+y > 0またはx+y < 0
**[x]~補~= 2^n+1^+x、[y]~補~ = y**
[x]~補~+[y]~補~ = (x+y)+2^n+1^ = [x+y]~補~ (mod 2^n+1^)
(4)x < 0、y < 0の場合、x+y < 0
**[x]~補~= 2^n+1^+x、[y]~補~ = 2^n+1^+y**
[x]~補~+[y]~補~ = 2^n+1^+x + 2^n+1^+y
= 2^n+1^+( 2^n+1^+x+y)
= [x+y]~補~ (mod 2^n+1^)
例: x=+1011 , y=-0101 , 求 x+y=?
解:[x]~補~ = **0**1011, [y]~補~ = **1**1011
[x]補 **0** 1 0 1 1
+ [y]補 **1** 1 0 1 1
————————————————
[x+y]補 **~~1~~ 0** 0 1 1 0
∴ x+y = +0110
1、符号位は数の一部として演算に参加する。
2、2n+1のモジュラスの意味において加算し、2n+1を超える進位は捨てられる。
##### 補码減法
減法を加算に変換するためには、次の公式を証明する必要がある:
$$ [x-y]_補=[x]_補-[y]_補 = [x]_補+[-y]_補 (mod 2^{n+1}) $$
[x-y]補= [x ]補- [ y]補=[x]補+[-y]補
(証明) 同時に[-y]補を求めるためには、[-y]~補~=乛[y]~補~+2^-n^(意味は[-y]~補~が[y]~補~の符号位を反転し、末位に1を加えたものであることを示す)
∵ [x]~補~+[y]~補~ = [x+y]~補~
∴ [y]~補~ = [x+y]~補~ - [x]~補~
また∵ [x-y]~補~ = [x+(-y)]~補~ = [x]~補~+[-y]~補~
∴ [-y]~補~ = [x-y]~補~ - [x]~補~
故[y]~補~ + [-y]~補~
= [x+y]~補~ - [x]~補~ + [x-y]~補~ - [x]~補~
= [x+y+x-y]~補~-[x+x]~補~
= [x+x]~補~ - [x+x]~補~
= 0
故[-y]~補~ = -[y]~補~(mod 2^n+1^)
**[X]~補~から[-X]~補~を求めるには:符号位を含めて各位を反転し、末位に1を加える**
#### 3. 定点数の乗除演算
##### 乗算演算
![ここに画像の説明を挿入](https://img-blog.csdnimg.cn/20210615165911334.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1ODkwNTMz,size_16,color_FFFFFF,t_70)
![ここに画像の説明を挿入](https://img-blog.csdnimg.cn/20210615173341744.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1ODkwNTMz,size_16,color_FFFFFF,t_70)![ここに画像の説明を挿入](https://img-blog.csdnimg.cn/20210615173417764.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1ODkwNTMz,size_16,color_FFFFFF,t_70)
##### 除算演算
**余り復元法**:被除数-除数、
結果が0より大きければ、商は1、余りを左にシフト。
結果が0より小さければ、商は0、余りを復元し、余りを左にシフト。
この操作を繰り返し、商の精度が要求を満たすまで続ける。
余りを復元しない方法( **加減交互法**)
- **最初**: 被除数と除数が同符号であれば、**被除数から除数を引く**;被除数と除数が異符号であれば、**被除数に除数を加える**
- **余りと除数が同符号であれば**、**商は1、余りを左にシフト**し、**除数を引く**;余りと除数が異符号であれば、**商は0、余りを左にシフト**し、**除数を加える**
- 商の末位は常に1に設定(誤差 2-n)、余りは負であっても復元する必要はない。
![ここに画像の説明を挿入](https://img-blog.csdnimg.cn/20210615172953483.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1ODkwNTMz,size_16,color_FFFFFF,t_70)
例:p44
![ここに画像の説明を挿入](https://img-blog.csdnimg.cn/2021061517345746.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1ODkwNTMz,size_16,color_FFFFFF,t_70)
#### 4. オーバーフローの概念と判別方法
##### オーバーフローの概念
定点整数機械において、数の表現範囲は **|x| < (2^n^-1)** であり、演算過程でワード長の絶対値を超える現象が発生した場合、「オーバーフロー」と呼ばれる。
[例15] x=+1011 , y=+1001 , 求 x+y 。
解:[x]~補~=01011 , [y]補=01001
[x]補 **0** 1 0 1 1
+ [x]補 **0** 1 0 0 1
——————————————
[x+y]補 **1** 0 1 0 0
二つの正数の和が負数になる結果は**上オーバーフロー**(結果が機械が表現できる最大正数を超える)
[例16] x=-1101 , y=-1011 , 求 x+y 。
解:[x]補=10011 , [y]補=10101
[x]補 **1** 0 0 1 1
+ [x]補 **1** 0 1 0 1
——————————————
[x+y]補 **0** 1 0 0 0
二つの負数の和が正数になる結果は**下オーバーフロー**(結果が機械が表現できる最小負数を下回る)
##### オーバーフローの検出
###### 二符号位法(変形補码)
加減算に参加する数は**変形補码**で表現される
[x]~補~=2^n+2^+x (mod 2^n+2^)
[x+y]~補~=[x]~補~+[y]~補~ (mod 2^n+2^)
- 二つの符号位がともに演算に参加する
- 2^n+2^のモジュラスの意味において加算し、最高符号位が生じる進位は捨てられる
Sf1 SF2
0 0 正しい(正数)
0 1 上オーバーフロー
1 0 下オーバーフロー
1 1 正しい(負数)
**二符号位が異なる**場合、**オーバーフロー**を示し、**同じ**場合は**オーバーフローがない**。 オーバーフローの有無にかかわらず、**Sf1(すなわち最高位)は結果の正しい符号を示す**
#### 練習問題
![ここに画像の説明を挿入](https://img-blog.csdnimg.cn/20210622103102351.JPG?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1ODkwNTMz,size_16,color_FFFFFF,t_70)
## 2.3 浮動小数点数の表現と演算
### 1. 浮動小数点数の表現
浮動小数点数の表現範囲
### 2. IEEE754標準。
### 3. 浮動小数点数の加減演算
1. 0操作数の**チェック**,簡略化操作の可能性を確認;
2. **階数**の大小を比較し、**対階**を完了する(小階を大階に合わせる);
3. **尾数**の**加算または減算**を行う;
4. 結果を**規格化**し、**丸め処理**を行う。
#### 対階
二つの数の階数を同じにするプロセスを実現する
**対階原則**:階数の小さい数を階数の大きい数に合わせる
**対階プロセス**:まず二つの数の階数E~x~とE~y~の差を求め、等しいかどうかを確認する。等しくない場合、尾数の移動によってE~x~とE~y~を変更し、すなわち対階を行い、等しくする。すなわち小階の尾数を右に移動させ(小数点を左に移動させるのと同じ)、右に1ビット移動するごとに、その階数を1加算し、二つの数の階数が等しくなるまで続ける。右に移動するビット数は階差に等しい。
#### 尾数の求和
方法は定点加減算と全く同じ
#### 規格化
浮動小数点数の規格化は**尾数域の最上位ビットが1であるべき**という要求があり、演算結果を**右にシフト**して規格化を実現することを**右規**と呼び、演算結果を**左にシフト**して規格化を実現することを**左規**と呼ぶ。
**規格化数の判断方法**(単一符号法)
- 原码:正数でも負数でも、最初の数位は1
- 反码、補码:符号位と最初の数位が異なる![ここに画像の説明を挿入](https://img-blog.csdnimg.cn/20210615174740285.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1ODkwNTMz,size_16,color_FFFFFF,t_70)
#### 丸め処理
丸め処理の目的:対階または右規の際、尾数が右にシフトされ、捨てられる低位部分が生じ、一定の誤差が生じる。誤差を減少させるため。
IEEE754標準の丸め処理
- 近似丸め(0捨て1入れ):「四捨五入」に似ており、捨てられる最高位が1であれば、1を加える
- 0に向かって丸め:単純な切り捨て
- +∞に向かって丸め:正数の余分なビットがすべて「0」でない場合、1を加える;負数は切り捨て
- -∞に向かって丸め:負数の余分なビットがすべて「0」でない場合、1を加える;正数は切り捨て
![ここに画像の説明を挿入](https://img-blog.csdnimg.cn/20210615175154740.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1ODkwNTMz,size_16,color_FFFFFF,t_70)![ここに画像の説明を挿入](https://img-blog.csdnimg.cn/20210615175250182.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1ODkwNTMz,size_16,color_FFFFFF,t_70)
![ここに画像の説明を挿入](https://img-blog.csdnimg.cn/20210615175326164.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1ODkwNTMz,size_16,color_FFFFFF,t_70)
![ここに画像の説明を挿入](https://img-blog.csdnimg.cn/20210615175355975.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1ODkwNTMz,size_16,color_FFFFFF,t_70)
## 2.4 算術論理ユニットALU
### 1. 直列加算器と並列加算器
1ビット全加算器の論理式は次の通り:
F~i~ = A~i~ ⊕ B~i~ ⊕ C~n+i~
C~n+i+1~ = A~i~B~i~ + A~i~C~n+i~ + B~i~C~n+i~
**Cは繰り上げ**
**直列加算器**
- 1つの全加算器しかなく、データは逐次的に加算器に送られ、演算が行われる。繰り上げフリップフロップは繰り上げ信号を保持し、次回の演算に参加する。
- 操作数がnビットの場合、加算はn回に分けて行われ、各回で1ビットの和が生成され、逐次的にレジスタに戻される。
**並列加算器**
- 並列加算器は複数の全加算器で構成され、そのビット数は機械のワード長と同じであり、各ビットデータが同時に演算される。
- 並列加算器の最長演算時間は主に繰り上げ信号の伝達時間によって決まる
- 並列加算器の各全加算器には低位からの繰り上げ入力と高位への繰り上げ出力がある
- 並列加算器の繰り上げは通常、直列繰り上げと並列繰り上げに分けられる。
### 2. 算術論理ユニットALUの機能と構造
![ここに画像の説明を挿入](https://img-blog.csdnimg.cn/20210615180544688.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1ODkwNTMz,size_16,color_FFFFFF,t_70)
ALUの論理図は上記の通り
F~i~ = X~i~ ⊕ Y~i~ ⊕ C~n+1~
C~n+i+1~ = X~i~Y~i~ + Y~i~C~n+1~ + X~i~C~n+1~
異なる制御パラメータにより異なる組み合わせ関数が得られ、さまざまな算術演算と論理演算を実現できる。
XiとYiと制御パラメータおよび入力量の関係は次の真値表で構成される
![ここに画像の説明を挿入](https://img-blog.csdnimg.cn/20210615181609181.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1ODkwNTMz,size_16,color_FFFFFF,t_70)