BigInt

    xiaoxiao2022-06-29  44

    题目

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


    调试错误解决

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

    转换到 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; }
    + 符号相同,那么设置符号,然后add符号不同,比较绝对值,取最大的,然后subtract判断是不是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咯,所以直接可用成员函数了


    - 不需要判断符号了,直接变为+ 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 } 加法 和的长度:number1和number2中长度最大的赋值就好了,最后若为1,就insert1number1和number2相差几位,在前面补0number2.insert(0, differenceInLength, '0'); // put zeros from leftfor循环从后往前,设置char carry = ‘0’保留进位for循环中的要有判断i!=0,第一位的进位在外面处理处理最高位的进位加法运算实现: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,就insert1number1和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 } }
    转载请注明原文地址: https://ju.6miu.com/read-1125502.html

    最新回复(0)