【问题标题】:bigInt addition and subtraction mattersbigInt 加减法事项
【发布时间】:2014-12-24 17:08:53
【问题描述】:

我目前正在做一项学校作业(很抱歉,我的问题是关于我的作业,但我不是在问代码中使用的算法)。我现在正在做算术部分,加法和减法。由于只有两个运算符,因此有 8 种运算组合。在我的程序中,我可以做到这四种情况:

(+a)+(+b) (-a)+(-b) (-a)-(+b) (+a)-(-b)

但是,我无法弄清楚其他四种情况的方法, 即

(+a)+(-b) (-a)+(+b) (-a)-(-b) (+a)-(+b)

真心希望各位大神能对这四种情况的处理提出建议和意见。

这是我的代码:

linkedListType.h: 是一个普通的链表头文件,这里就不贴出全部代码了。

大整数.h: 这里面的函数很长。因此,我跳过了将它们发布出去。

#ifndef BIG_INTEGER_H
#define BIG_INTEGER_H

#include <stack>  
#include <iostream>
#include "linkedListType.h"

using namespace std;

class bigInteger
{
private:
    int sign;                       // set 0 for positive, 1 for negative
    linkedListType<int> digits;     // internal linked-list for storing digits in reverse order

public:
    bigInteger();                           // default constructor
    bigInteger(const bigInteger& other);    // copy constructor

    // Overload constructor
    // Use an numerical string to construct this bigInteger
    // For negative number, the first char in the string is '-'
    // e.g. "-12345"
    bigInteger(const string& number);       

    // overload the assignment operator
    const bigInteger& operator= (const bigInteger& other);

    // Return a new bigInteger that is equal to *this + other
    // The contents of this and other should not be modified
    bigInteger& operator+ (bigInteger& other);

    // Return a new bigInteger that is equal to *this - other
    // The contents of this and other should not be modified
    bigInteger& operator- (bigInteger& other);

    // Print a big integer
    // Since the digits are stored in reverse order in the internal
    // list, you should print in reverse order
    // Print "undefined" if the digits list is empty
    friend ostream& operator<<(ostream& os, bigInteger& n);
};

【问题讨论】:

  • 您应该添加一元运算符 - 例如见here。还要注意它不应该是 bigInteger&amp; operator+ (bigInteger&amp; other); 而是 bigInteger operator+(const bigInteger&amp; other); 即返回 by value 并通过 const 引用获取参数。你可能想写bigInteger&amp; operator+=(const bigInteger&amp; other);(和operator-=),然后你可以把+写成这样的非成员函数:bigInteger operator+(bigInteger lgs, const bigInteger&amp; rhs) { return lhs += rhs; }
  • 同样,friend ostream&amp; operator&lt;&lt;(ostream&amp; os, bigInteger&amp; n); 应该采用const bigInteger&amp; n
  • 感谢您的建议@TonyD。但是,我可以问一些问题吗?您介意解释一下一元运算符的用途吗?还有,+=和-=的作用是什么?
  • 我不明白你的问题。而且您发布的代码不太可能足以让任何人帮助您。 (另外,“反向”不是一个词。)
  • @user2847449:当然 - 欢迎提问。假设你有bigInteger x; 并写成-x,如果没有“左侧”可以减去x,编译器将寻找bigInteger bigInteger::operator-() 函数并调用它——它应该返回*this 的否定- 在上面的链接问题中对此进行了解释。 +=-= 从左侧的值中加减一个数量,因此如果运算符“正常”实现,x = x + 3 可以方便地缩短为 x += 3。如果你写的是+-,人们也会期待+=-=

标签: c++ math bigint


【解决方案1】:

所有的 cmets 都在处理运算符重载的东西,但我怀疑 OP 是关于如何计算操作数符号的所有组合以进行加法和减法。

  1. 二的补码

    大多数 HW 整数 ALU 实现使用二进制补码表示有符号数。这意味着:

    -X = (X^0xFFFFFFFF)+1; // 32 bit example
    

    仅通过反转所有位并增加结果而获得的负值。因此,当符号位仍为 MSB 时,您可以对所有加法/减法和符号组合使用单加法器架构。这种编码处理有符号和无符号操作的方式相同,因此对于加法,您完全没有问题(只需添加即可),而对于减法,只需反转第二个操作数的符号并添加。

    C++ 实现如下所示:

    bool bigInteger::sign() { return MSB_of_this; }
    bigInteger bigInteger::operator+ () { bigInteger z=*this; return z; }
    bigInteger bigInteger::operator- () { bigInteger z=*this; /* here negate all bits and increment z*/ return z' |z; }
    bigInteger bigInteger::operator+ (bigInteger& y)
     {
     bigInteger z;
     // here do z = *this + y as if all operands were positive
     return z;
     }
    
    bigInteger bigInteger::operator- (bigInteger& y0)
     {
     bigInteger z;
     y=-y0; // invert sign in temp variable to avoid changing input operand value !!!
     // here do z = *this + y as if all operands were positive
     return z;
     }
    

    请注意,我没有更改任何输入操作数,并且所有返回都是单独的变量(即使对于一元+也不使用它)。这是由于操作数的链式能力。如果不以这种方式编码,一些编译器很难在一行中菊花链超过 3 个运算符,这意味着您无法编译像

    这样的行
    c=a+b-c*a*b/(s-d)+(23*q);
    

    相反,您必须将其分解为更简单的术语...

  2. 如果你不使用补码

    然后你必须处理输入操作数的符号。最常见的情况是您将符号标志作为单独的变量,而不是在数字位内。在这种情况下,您需要一些根本不考虑登录的功能

    bigInteger uadd(bigInteger &a,bigInteger &b); //=|a|+|b|
    bigInteger usub(bigInteger &a,bigInteger &b); //=|a|-|b| but operands must be: |a|>|b|
    bool        ugeq(bigInteger &a,bigInteger &b); //=|a|>=|b| Unsigned Greater or EQual
    

    这很容易

    加法

    • 只有相同符号的数字才能相加,否则将其转换为减法

    减法

    • 只有当数字是相同的符号并且第一个操作数大于或等于第二个操作数时,您才能对数字进行子分类。

    所以应该是这样的:

    bigInteger bigInteger::operator+ (bigInteger& y)
     {
     bigInteger z;
     bool sx,sy;
     sx=sign();
     sy=y.sign();
     if (sx==sy) z=uadd(*this,y);  // same signs is add
     else                            // not then first operand for (a-b) is the positive one
      {
      if (sx) return y-(*this);
      else    return (*this)-y;
      }
     // here set the sign to the same as operands
     z.set_sign(sx);
     return z;
     }
    

    因为这是一个分配,我将留下 - 运算符没有代码。

    这将与+ 运算符非常相似,但您需要按绝对大小对输入操作数进行排序(使用ugeq)并将结果sign 设置为abs 较大的值。如果您交换了操作数,则反转结果的符号。仅当展位操作数是相同符号时才减去,否则转换为 (a+b) ...

希望对你有帮助

【讨论】:

  • 只是我的预感,但鉴于问题是“用于存储数字的内部链表”,我怀疑每个列表元素都有一个数字,并且按位操作/2s 补充了您记录的方面并且需要了解此初学者作业不需要高效打包和快速的bigInteger 类型.....
  • @TonyD 嗯,我假设 2^8+ 整数基数,但是是的,它们更有可能只是数字。答案的后半部分应涵盖其余部分,否则由她/他来澄清谜题中缺少的内容...
猜你喜欢
  • 1970-01-01
  • 2020-02-13
  • 1970-01-01
  • 1970-01-01
  • 2021-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多