-4

我只使用逻辑门在 C 中制作二进制加法器。例如,现在我想添加4 + (-5),所以我会在 2 的补码中得到答案,然后将其转换为十进制。同样,如果我这样做,4 + (-3)我会得到二进制的答案,并想使用相同的函数将其转换为十进制。

现在,我知道如何将 2 的补数转换为十进制,将二进制转换为十进制。但我想使用相同的函数将 2 的补码和二进制转换为十进制。为此,我必须弄清楚数字是二进制还是 2 的补码。这是我卡住的地方。

有人可以给我一个想法、算法或 C 代码来找出一个数字是 2 的补码还是正常的二进制?

源代码

筹码

// 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)));
}

我们的hdr.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 *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;
}

将二进制转换为十进制的函数,反之亦然

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;
    }
}

主要程序设计

  • 从用户读取两个n1数字n2
  • 获取一个指针bits1bits2它指向一个数组,其中包含 和 的n1n2。请注意,数组的顺序是相反的,即最后一位将在0th数组的变量中。
  • 放置一个 for 循环,您将在其中传递三个变量,即您要添加的位和最后一次添加位操作的进位。
  • 返回值将是三位和进位的加法,加法后将更改为进位(如果有)。例如,您通过1and 0,并且进位是1,因此,返回将是0并且进位将再次更改为1
  • 返回值将存储在另一个名为sum.
  • 数组sum将使用我上面给出的函数转换为 int。
  • 现在这就是我卡住的地方。我现在想将 int 更改为十进制数。但要做到这一点,我必须知道它是 2 的补码形式,还是只是普通的二进制形式。我不知道该怎么做。

注意:这个nand2tetris项目是用 C 完成的,hdl但我很熟悉用 C 来完成。此外,我上面提到的许多功能都取自stackoverflow. 虽然,设计是我自己的。

4

2 回答 2

4

两者都是二进制的。区别是signedunsigned。因为>0这是一样的。因为<0只要看最高位就可以看出它是一个负数。通过查看最高位可以很容易地使用相同的函数进行输出,如果它设置为输出'-'并将负二进制补码转换为它abs()可以很容易地按位完成。

注意:如果一个正数大到足以设置最高位,它就不能再与负二进制补码区分开来。这就是为什么编程语言确实需要单独的类型的原因(例如在 Cint和中unsigned)。

于 2016-01-13T13:39:53.460 回答
0

关于 2s 补码的有趣事实 - 它被广泛使用的原因是:

此外,您不需要知道它是消极的还是积极的。只需添加为未签名即可。

减法类似,但您必须否定第二个操作数(见下文)。

您可能需要关心的唯一一件事就是溢出。为此,您必须检查结果的符号是否实际上可以由两个输入的符号以及从最前位到最重要位的加法溢出产生。

的否定int n只是由 完成0 - n。或者,您可以反转所有位并添加1- 这就是 CPU 或硬件减法器的基本功能。

请注意,2 的补码二进制文件具有不对称范围:-(N+1) ... N.

对于转换,只需检查最小值(必须单独处理)并直接输出,否则获取符号(if ( n < 0 ))并将值取反(n = -n)最后将 -then unsigned/positive - 值转换为字符串或字符流。

于 2016-01-13T13:58:27.110 回答