BigInt

题目

用string模拟int大数运算,记得网易的一个笔试题最后就是的


调试错误解决

  1. #include 依旧报错string未定义
    因为木有using namespace std;

  2. 转换到 coff 期间失败
    项目属性 — 配置属性 — 清单工具 — 点击输入输出
    将右侧出现的嵌入清单的属性值修改为否,点击应用,点击确定


参考程序地址

github-BigInteger


Code

成员变量

private
string num; // 数值
bool sign; //符号信息: true:负数 false:正数或者0
所以需要setNum,setSign和getNum,getSign

构造函数

1. BigInteger(); // empty constructor initializes zero
    sign:false num = "0",初始化为0
2. BigInteger(string s); // "string" constructor
    判断第一位 isdigit(s[0]) ,是,sign=false整数, 调用setNumber(s)
    否,sign =  (s[0] == '-'); 可能为+、-,调用 setNumber( s.substr(1) )从第二位(下标1)开始
3. BigInteger(string s, bool sin); // "string" constructor
    直接调用 setNumber(s),setSign(sin)
4. BigInteger(int n); // "int" constructor
    用到了stringstream作为中间,将int为变为string,同样判断是否正负,同2

附1: substr用法:
substr 方法
返回一个从指定位置开始,并具有指定长度的子字符串。
参数 :
start 必选。所需的子字符串的起始位置。字符串中第一个字符的索引为 0。
length : 可选项。返回的子字符串中包含的字符数。
备注
如果 length 为 0 或负数,将返回一个空字符串。如果没有指定该参数,则子字符串将延续到字符串的结尾。

附2:int–string

   int n;
   stringstream ss;
    string s;
    ss << n;
    ss >> s;

成员函数set get

void BigInteger::setNumber(string s) {
    number = s;
}

const string& BigInteger::getNumber() { // retrieves the number
    return number;
}

void BigInteger::setSign(bool s) {
    sign = s;
}

const bool& BigInteger::getSign() {
    return sign;
}

运算符重载

=,==,!=,>,<,>=,<=,++(前缀,后缀), --(前缀,后缀), +,-,/,%,+=,*=,/+,%=
这里重载了好多
不过可以明显从看到代码中 i++和++i的区别了
重载运算符,已经默认传了this指针


  • ++i
BigInteger& BigInteger::operator ++() { // prefix
    (*this) = (*this) + 1;
    return (*this);
}

  • i++
BigInteger BigInteger::operator ++(int) { // postfix
    BigInteger before = (*this);

    (*this) = (*this) + 1;

    return before;
}

  • +
    1. 符号相同,那么设置符号,然后add
    2. 符号不同,比较绝对值,取最大的,然后subtract
    3. 判断是不是0,一面出现‘-0’的情况
BigInteger BigInteger::operator + (BigInteger b) {
    BigInteger addition;
    if( getSign() == b.getSign() ) { // both +ve or -ve
        addition.setNumber( add(getNumber(), b.getNumber() ) );
        addition.setSign( getSign() );
    } else { // sign different
        if( absolute() > b.absolute() ) {
            addition.setNumber( subtract(getNumber(), b.getNumber() ) );
            addition.setSign( getSign() );
        } else {
            addition.setNumber( subtract(b.getNumber(), getNumber() ) );
            addition.setSign( b.getSign() );
        }
    }
    if(addition.getNumber() == "0") // avoid (-0) problem
        addition.setSign(false);

    return addition;
}

代码中看出来,this指针就是a咯,所以直接可用成员函数了


  • -
    1. 不需要判断符号了,直接变为+
BigInteger BigInteger::operator - (BigInteger b) {
    b.setSign( ! b.getSign() ); // x - y = x + (-y)
    return (*this) + b;
}

  • 大于>
    在判断绝对值的时候用到了重载的大于
bool BigInteger::operator > (BigInteger b) {
    return greater((*this) , b);
}

计算函数

  • 绝对值
    直接返回getNum, 有够了一个BigInteger类,传string参数的那个构造函数
BigInteger BigInteger::absolute() {
    return BigInteger( getNumber() ); // +ve by default
}
  • 加法
    1. 和的长度:number1和number2中长度最大的赋值就好了,最后若为1,就insert1
    2. number1和number2相差几位,在前面补0number2.insert(0, differenceInLength, '0'); // put zeros from left
    3. for循环从后往前,设置char carry = ‘0’保留进位
    4. for循环中的要有判断i!=0,第一位的进位在外面处理
    5. 处理最高位的进位
    6. 加法运算实现:add[i] = ((carry-'0')+(number1[i]-'0')+(number2[i]-'0')) + '0';
string BigInteger::add(string number1, string number2) {
    string add = (number1.length() > number2.length()) ?  number1 : number2;
    char carry = '0';
    int differenceInLength = abs( (int) (number1.size() - number2.size()) );

    if(number1.size() > number2.size())
        number2.insert(0, differenceInLength, '0'); // put zeros from left

    else// if(number1.size() < number2.size())
        number1.insert(0, differenceInLength, '0');

    for(int i=number1.size()-1; i>=0; --i) {
        add[i] = ((carry-'0')+(number1[i]-'0')+(number2[i]-'0')) + '0';

        if(i != 0) {
            if(add[i] > '9') {
                add[i] -= 10;
                carry = '1';
            } else
                carry = '0';
        }
    }
    if(add[0] > '9') {
        add[0]-= 10;
        add.insert(0,1,'1');
    }
    return add;
}
  • 减法
  • 差的长度:number1和number2中长度最大的赋值就好了,最后若为1,就insert1
  • number1和number2相差几位,在前面补0number2.insert(0, differenceInLength, '0'); // put zeros from left
  • 减法是要从高位借位(可以不用考虑0吧,反正小的话会借位,会+10)
  • sub[i] = ((number1[i]-'0')-(number2[i]-'0')) + '0';
  • 除去最开始的0,erase,所以只需要最开始位不为0,以及最后长度要>=1
string BigInteger::subtract(string number1, string number2) {
    string sub = (number1.length()>number2.length())? number1 : number2;
    int differenceInLength = abs( (int)(number1.size() - number2.size()) );

    if(number1.size() > number2.size())
        number2.insert(0, differenceInLength, '0');

    else
        number1.insert(0, differenceInLength, '0');

    for(int i=number1.length()-1; i>=0; --i) {
        if(number1[i] < number2[i]) {
            number1[i] += 10;
            number1[i-1]--;
        }
        sub[i] = ((number1[i]-'0')-(number2[i]-'0')) + '0';
    }

    while(sub[0]=='0' && sub.length()!=1) // erase leading zeros
        sub.erase(0,1);

    return sub;
}
  • 大于
    逻辑就是不等于不小于
bool BigInteger::greater(BigInteger n1, BigInteger n2) {
    return ! equals(n1, n2) && ! less(n1, n2);
}
  • 等于
    string相等就是的了且符号相等
bool BigInteger::equals(BigInteger n1, BigInteger n2) {
    return n1.getNumber() == n2.getNumber()
           && n1.getSign() == n2.getSign();
}
  • 小于
  • 先看符号,不同的话就是正的大
  • 符号相同,都是正,那个长哪个大,否则长度相同,直接比较string
  • 符号相同,都是负,那个长哪个小,否则长度相同,直接比较string
bool BigInteger::less(BigInteger n1, BigInteger n2) {
    bool sign1 = n1.getSign();
    bool sign2 = n2.getSign();

    if(sign1 && ! sign2) // if n1 is -ve and n2 is +ve
        return true;

    else if(! sign1 && sign2)
        return false;

    else if(! sign1) { // both +ve
        if(n1.getNumber().length() < n2.getNumber().length() )
            return true;
        if(n1.getNumber().length() > n2.getNumber().length() )
            return false;
        return n1.getNumber() < n2.getNumber();
    } else { // both -ve
        if(n1.getNumber().length() > n2.getNumber().length())
            return true;
        if(n1.getNumber().length() < n2.getNumber().length())
            return false;
        return n1.getNumber().compare( n2.getNumber() ) > 0; // greater with -ve sign is LESS
    }
}

你可能感兴趣的:(数据结构)