减去不带补码的有符号二进制数

时间:2018-10-23 23:51:04

标签: c binary arbitrary-precision

所以我试图编写代码以减去两个二进制数,但是我不确定如何优雅地解决此问题。保留二进制数的结构如下。

typedef struct _bitb {
    short bit;
    struct _bitb *nbit;
} BitB;
typedef struct _bignum {
    short sign;
    BitB *bits;
} BigNum;

因此,一个二进制数由一个包含其绝对值的位的列表(从LSB到MSB)表示,然后用一个简短的数字表示该数字是正数还是负数(这是一种任意精度算法的实现)。如何在不带补码的情况下从另一个中减去一个数?

在有人问之前,这是上学的时间,但是我不想要代码中的解决方案,而只是可以实现的通用算法。我一直在搜索,似乎没有一种可以解决一般情况的好的算法。我是否需要检查数字的符号,然后针对所有可能的情况(负负正数,正负负数,正负正数,负负正数)实施代码?还是我应该转换为2的补码?

3 个答案:

答案 0 :(得分:4)

  

这是上学的时间,但是我不想要代码中的解决方案,而只是可以实现的通用算法

BigNum是整数的符号幅度链接列表编码。

要添加/减去BigNum,需要编写代码以添加/减去每个BitB操作数的大小。

要增加幅度,可以很容易地遍历BitB链表并随手形成和。

// pseudo-code
BitB *BitBAdd(const BitB *a, const BitB *b) {
  BitB temp_head = set next member to NULL
  BitB *bit_walker = pointer to the head
  bool carry = false;
  while (a is not end of list, b not end of list, or carry) {
    bool abit = get bit from a if not NULL and advance a, else 0
    bool bbit = get bit from b if not NULL and advance b, else 0
    bit_walker->nbit =  malloc(sizeof *(bit_walker->nbit));
    check allocation success
    advance bit_walker
    set bit_walker->nbit members to NULL, abit ^ bbit ^ carry
    carry = majority(abit, bbit, carry);
  }
  return temp_head.nbit;
}

幅度的减法要求首先找到一个大的int BitBCmp(const BitB *a, const BitB *b)。代码未显示。减法函数BitB *BitBCmp(const BitB *larger, const BitB *smaller)类似于BitBAdd()。未显示。

一旦制作了BitBAdd()BitBCmp()BitBSub(),然后可以通过检查符号并调用各种{{1}来制作BigNum_Add()BigNum_Sub() },如@user3386109所建议。


侧面问题

BitB...()约占完成OP任务所需代码的20-25%。

可能需要将最高有效的零位数字掉下来。还应考虑符号幅度编码可以生成+0和-0。

答案 1 :(得分:2)

您可以将问题减少为两种情况:符号相反和符号相同。

减去具有相反符号的数字需要将两个绝对值相加。例子:

(-7) - (+5) = -(7+5)
(+7) - (-5) = +(7+5)

要减去具有相同符号的数字,需要从较大的绝对值中减去较小的绝对值。例子:

(+7) - (+5) = +(7-5)
(+7) - (+9) = -(9-7)
(-7) - (-5) = -(7-5)
(-7) - (-9) = +(9-7)

如您所见,结果的符号实际上有6种情况,如下所示(其中X,Y和Z是数字的大小)。

(-X) - (+Y) ==> -(Z)
(+X) - (-Y) ==> +(Z)
(+X) - (+Y) and (X >= Y) ==> +(Z)
(+X) - (+Y) and (X <  Y) ==> -(Z)
(-X) - (-Y) and (X >  Y) ==> -(Z)
(-X) - (-Y) and (X <= Y) ==> +(Z)

总结:

如果两个数字的符号相反,则将其大小相加。
如果两个数字具有相同的符号,则从较大的幅度中减去较小的幅度。
然后确定结果的符号。

答案 2 :(得分:0)

对于A-B,其中|A| < |B|,您需要2的补全。例如如果A = 2B = 5A-B将是-3,则必须取结果的2的补码。 -(5-3)。在任何情况下,您都必须使用2的补码。

我建议您使用2的补码将减法转换为加法。

即如果您有ans = A-B,则取B的2的补码,然后加。

然后您将获得ans = A + (-B)

第1步。取B的2的补码

步骤2。将A加上2的补码。

这将在很大程度上简化代码。

这也是在CPU内部处理数字减法的方法。