-4

論理ゲートのみを使用して C で 2 進加算器を作成していました。4 + (-5)たとえば、 2 の補数で答えを得て、それを 10 進数に変換するために足し算をしたかったのです。同様に、私がそうするなら、4 + (-3)私は2進数で答えを得て、同じ関数を使ってそれを10進数に変換したいと思います。

これで、2 の補数を 10 進数に変換する方法、2 進数を 10 進数に変換する方法がわかりました。しかし、同じ関数を使用して、2 の補数と 2 進数の両方を 10 進数に変換したいと考えています。そのためには、数値が 2 進数か 2 の補数かを判断する必要があります。それは私が立ち往生しているところです。

ある数値が 2 の補数なのか通常の 2 進数なのかを調べるためのアイデア、アルゴリズム、または C のコードを教えてもらえますか?

ソースコード

チップス

// Author: Ashish Ahuja
// Date created: 8-1-2016
// Descriptions: This file stores all the chips for
//               the nand2tetris project.
// Links: www.nand2tetris.org
//        class.coursera.org/nand2tetris1-001
// Files needed to compile successfully: ourhdr.h

int not (unsigned int a) {
    if (a == 1) {
          return 0;
    }
    else if (a == 0) {
          return 1;
    }
}

int and (unsigned int a, unsigned int b) {
    if (a == 1 && b == 1)
          return 1;
    else if ((a == 1 && b == 0) || (a == 0 && b == 1) || (a == 0 && b == 0))
          return 0;
}

int nand (unsigned int a, unsigned int b) {
    unsigned int ans = 10;
    ans = and (a, b);
    unsigned int ack = not (ans);
    return ack;
}

int or (unsigned int a, unsigned int b) {
    return (nand (not (a), not (b)));
}

int nor (unsigned int a, unsigned int b) {
    return (not (or (a, b)));
}

int xor (unsigned int a, unsigned int b) {
    unsigned int a_r;
    unsigned int b_r;
    unsigned int sra;
    unsigned int srb;
    a_r = not (a);
    b_r = not (b);
    sra = nand (a_r, b);
    srb = nand (b_r, a);
    return nand (sra, srb);
}

int xnor (unsigned int a, unsigned int b) {
    return (not (xor (a,b)));
}

Ourhdr.h

include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <math.h>
#include <time.h>
#include <stdbool.h>
#include <termios.h>
#include <stddef.h>
#include <sys/types.h>
#include <my/signal.h>
#include <my/socket.h>
#include <my/io.h>
#include <my/lib.h>
#include <my/tree.h>
#include <my/bits.h>
#include <my/binary.h>
//#include <my/error.h>

#define MAXLINE 4096
#define BUFF_SIZE 1024

注: このプロジェクトに必要なヘッダーのみを表示します。したがって、他のヘッダーは役に立たないと考えてください。

配列を整数に変換する関数

int array_num (int arr [], int n) {
    char str [6] [2];
    int i;
    char number [13] = {'\n'};
    for (i = 0; i < n; i ++)
        sprintf (str [i], "%d", arr [i]);
    for (i = 0; i < n; i ++)
        strcat (number, str [i]);
    i = atoi (number);
    return i;
}

int のビットを取得し、ビットを含む配列へのポインターを返す関数

int *get_bits (int n, int bitswanted) {
    int *bits = malloc (sizeof (int) * bitswanted);
    int k;
    int mask;
    int masked_n;
    int thebit;
    for (k = 0; k < bitswanted; k ++) {
        mask = 1 << k;
        masked_n = n & mask;
        thebit = masked_n >> k;
        bits [k] = thebit;
    }
    return bits;
}

2 進数を 10 進数に、またはその逆に変換する関数

int convert_num (int n, int what) {
    int rem;
    int i;
    int binary = 0;
    int decimal = 0;

    switch (what) {
        case 0:                    // Convert decimal to binary
             i = 0;
             rem = 0;
             while (n != 0) {
                   rem = n % 2;
                   n /= 2;
                   binary += rem * i;
                   i *= 10;
             }
             return binary;
             break;
        case 1:                   // Convert binary to decimal
             i = 0;
             rem = 0;
             while (n != 0) {
                   rem = n % 10;
                   n /= 10;
                   decimal += rem*pow (2, i);
                   i ++;
             }
             return decimal;
             break;
    }
}

メインプログラムの設計

  • n12 つの数値を読み取りn2、ユーザーから
  • およびのビットを持つ配列を指すポインターbits1およびを取得します。配列は逆順になることに注意してください。つまり、最後のビットが配列の変数になります。bits2n1n20th
  • 3 つの変数を渡す for ループを配置します。つまり、追加したいビットと、最後のビット追加操作からのキャリーです。
  • 戻り値は 3 つのビットと桁上げの加算であり、加算後の桁上げ (ある場合) に変更されます。1例: あなたはandを渡し0、キャリーは です1。したがって、リターンは になり0、キャリーは に再び変更され1ます。
  • 戻り値は、 という別の配列に格納されsumます。
  • 配列sumは、上記の関数を使用して int に変換されます。
  • 今、これが私が立ち往生しているところです。int を 10 進数に変更したいと思います。しかし、それを行うには、それが 2 の補数の形式なのか、それとも単なる 2 進数なのかを知る必要があります。私はそれを行う方法がわかりません。

注:プロジェクトnand2tetrisは で行われますhdlが、私は C で行うことに慣れていました。また、上で述べた関数の多くはstackoverflow. とはいえ、デザインは私のものです。

4

2 に答える 2

0

2 の補数についての楽しい事実と、2 の補数が非常に広く使用されるようになった理由は次のとおりです。

さらに、それが負か正かを知る必要はありません。署名なしで追加するだけです。

減算も同様ですが、2 番目のオペランドを否定する必要があります (以下を参照)。

気にしなければならない唯一のことは、オーバーフローです。そのためには、結果の符号が実際に 2 つの入力の符号と最上位ビットから最上位ビットへの加算オーバーフローの結果であるかどうかを確認する必要があります。

の否定はint nで簡単にでき0 - nます。または、すべてのビットを反転して加算することもできます1。これは、CPU またはハードウェアの減算器が基本的に行うことです。

2 の補数のバイナリには非対称の範囲があることに注意してください: -(N+1) ... N.

変換の場合は、最小値 (個別に処理する必要があります) をチェックして直接出力します。それ以外の場合は、符号 ( if ( n < 0 )) を取得し、値を否定 ( n = -n) し、最後に符号なし/正の値を文字列または文字ストリームに変換します。

于 2016-01-13T13:58:27.110 に答える