C言語による半加算器、全加算器 その2

イチケンさんの Youtube 動画を見ていたら「NAND ゲートだけの組み合わせで NOT/AND/OR/NOR が作れる」と知り、過去に書いたソフトウェア加算器を書き直してみました。動画では触れられていませんでしたが、XOR もちゃんと作れるみたい。

#include <stdio.h>
#define NBBITS 8

/* 論理ゲート */
int _nand(int a, int b) { return (!a && !b) || (!a &&  b) || (a && !b); }
int _not(int a) { return _nand(a, a); }
int _and(int a, int b) { return _not(_nand(a, b)); }
int _or(int a, int b) { return _nand(_nand(a, a), _nand(b, b)); }
int _nor(int a, int b) { return _not(_or(a, b)); }
int _xor(int a, int b) { return _nand(_nand(a, _nand(a, b)), _nand(b, _nand(a, b))); }

/* 半加算器 */
int half_adder(int a, int b, int* res)
{
  *res = _xor(a, b);
  return _and(a, b); // carry
}

/* 全加算器 */
int full_adder(int a, int b, int carry, int* res)
{
  int carry1 = half_adder(a, b, res);
  int carry2 = half_adder(*res, carry, res);
  return _or(carry1, carry2); // carry
}

/* 複数ビット加算器 */
void multibit_adder(int a[], int b[], int res[])
{
  int carry;
  for (int i = 0; i < NBBITS; i++) {
    if (i) {
      carry = full_adder(a[i], b[i], carry, &res[i]);
    }
    else {
      carry = half_adder(a[i], b[i], &res[i]);
    }
  }
}

/* 複数ビット減算器 */
void multibit_subber(int a[], int b[], int res[])
{
  int carry = 1;
  for (int i = 0; i < NBBITS; i++) {
    carry = full_adder(a[i], _not(b[i]), carry, &res[i]);
  }
}

/* 内容を印字する(左が小さい桁) */
void dump(int a[])
{
  for (int i = 0; i < NBBITS; i++) { printf("%d", a[i]); }
  puts("");
}

int main()
{
  /* 左が小さい桁 */
  int a[] =   {1, 0, 0, 0, 0, 0, 0, 0};
  int b[] =   {0, 1, 0, 0, 0, 0, 0, 0};
  int res[] = {0, 0, 0, 0, 0, 0, 0, 0};

  puts("a + b =");
  multibit_adder(a, b, res);
  dump(a);
  dump(b);
  dump(res);
  puts("");

  puts("a - b =");
  multibit_subber(a, b, res);
  dump(a);
  dump(b);
  dump(res);
  puts("");

  return 0;
}

加算器を作るだけだったら、NOR ゲートは不要ですがついでに実装。10進数で表現すると、a = 1, b = 2 となります。出力は次のとおり。

a + b =
10000000
01000000
11000000

a - b =
10000000
01000000
11111111

2進数の列は左が小さい桁です。

1 - 2 がちゃんとマイナス値になっているのが楽しい。コンピューターで何故 0xFF が -1 として扱われるか、よく分かりますね。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください