大数运算之字符串模仿
副问题[/!--empirenews.page--]
? 信托各人被出格大的两个数据做运算熬煎过。当两个操纵数可能运算功效高出范例的暗树模畴后会故意想不到的错误,这时辰我们的电脑还不如我们高顶用过的科学计较器,这是作为一个措施员所不能忍受的。以是我们得找到其他的方法来计较。这就是我们本日要接头的字符串模仿大数运算。 ?我们的运算一样平常行使int范例来算的,那么起首我们先温习一下各类int范例的数据暗树模畴: unsigned?int?0~4294967295??? int???-2147483648~2147483647? unsigned?long?0~4294967295 long???-2147483648~2147483647 long?long的最大值:9223372036854775807 long?long的最小值:-9223372036854775808 unsigned?long?long的最大值:1844674407370955161 __int64的最大值:9223372036854775807 __int64的最小值:-9223372036854775808 unsigned?__int64的最大值:18446744073709551615 可以看到,在64位操纵体系下,long long int暗示的最大范畴是-9223372036854775808--9223372036854775807以是当我们的两个操纵数可能运算功效高出这个范畴我们就界说它已经溢出,得用字符串来模仿运算。以是我们得有一个_IsINT64OverFlow()函数,用来判定是否溢出: bool?BigData::?_IsINT64OverFlow()const { if?(_value?>=?Min_INT64?&&?_value?<=?Max_INT64) return?false; return?true; } ? 我们是用字符串来模仿的,用一个类来封装大数运算的加减乘除这些成果,以是先计一律下BigData这个类的根基构架。 #ifndef?BIGDATA1_H #define?BIGDATA1_H #include<iostream> #include<string> #include<assert.h> #define?Max_INT64?9223372036854775807 #define?Min_INT64?(-9223372036854775807-1) //不能直接用-9223372036854775808,当编译器看到9223372036854775808时直接鉴定 //9223372036854775808>INT64_MAX,直接用unsigned?int64暗示。当编译器看到负号时, //直接对9223372036854775808取反,直接是它自己,编译器存不了那么大的数,报错 #define?INT64?long?long?int using?namespace?std; class?BigData { public: BigData(INT64?data); BigData(const?char?*str); BigData?operator+(BigData&?d);//加法 BigData?operator-(BigData&?d);//减法 BigData?operator*(BigData&?d);//乘法 BigData?operator/(BigData&?d);//除法 private: friend?string?Add(string&?left,?string&?right); friend?string?Sub(string&?left,?string&?right); friend?string?Mul(string&?left,?string&?right); friend?string?Div(string&?left,?string&?right); bool?_IsINT64OverFlow()const;//判定数据是否溢出 friend?ostream&?operator<<(ostream&?_cout,?const?BigData&?d); void?_INT64ToString();//将long?long?int数据转换成字符串 private: string?_strvalue; INT64?_value; }; #endif ?这里有一个题目就是在用-9223372036854775807暗示INT64_MIN时呈现了一些题目; ? error C4146: 一元负运算符应用于无标记范例,功效仍为无标记范例。 当时辰各类搞不懂,然后就查了一下列位大神的表明,概略意思就是不能直用-9223372036854775808暗示。当编译器看到9223372036854775808时直接鉴定9223372036854775808>INT64_MAX,直接用unsigned int64暗示。当编译器看到负号时,直接对9223372036854775808取反,直接是它自己,编译器存不了那么大的数,编译器就报错。具体表明见一元负运算符。 ? 此刻概略的框架已经搭好了。来看具体的实现进程: (一)两个结构函数 BigData::BigData(INT64?data) :_value(data) { _INT64ToString(); } BigData::BigData(const?char?*str) :?_value(0) { if?(str?==?NULL) { assert(false); return; } char?symbol; if?(str[0]?==?'+') { symbol?=?'+'; str++; } else?if?(str[0]?==?'-') { symbol?=?'-'; str++; } else?if?(str[0]?>=?'0'&&str[0]?<=?'9') { symbol?=?'+'; } else { return; } char*?tmpstr?=?(char*)str; while?(*tmpstr?==?'0')//跳过前面的‘0’ tmpstr++; int?i?=?0;//剩下字符串的长度 while?(*tmpstr?>=?'0'&&?*tmpstr?<=?'9') { i++; _value?=?_value?*?10?+?*tmpstr?-?'0'; tmpstr++; } if?(symbol?==?'-') { _value?=?0?-?_value; } _strvalue.resize(i?+?1);//相等于给_strvalue开发空间 _strvalue[0]?=?symbol; int?j?=?1; while?(i--) { _strvalue[j++]?=?*str++; } } void?BigData::_INT64ToString() { INT64?tmp?=?_value; INT64?sym?=?tmp; string?str; if?(sym?>=?0) { str.push_back('+'); } else { str.push_back('-'); tmp?=?0?-?tmp; } while?(tmp) { char?ctmp?=?tmp?%?10?+?'0'; str.push_back(ctmp); tmp?/=?10; } int?right?=?str.size()-1; int?left?=?1; while?(left?<?right) { swap(str[left++],?str[right--]); } _strvalue?=?str; } ? 行使字符串结构较量贫困,我们在结构_strvalue的时辰还要把字符串数据转换为long long int范例的_value,利便往后计较,假如字符串暗示的数据没有溢出的话直接用内置的long long int来计较。字符串转换为int的重点就是要从字符串的最后一个字符开始转化,每次轮回数据乘以10。最后可以算出整个字符串的值,假如是负数,用0-_value即可。 ? 尚有long long int范例转换为字符串函数。算法不难,只是字符串的第一个字符统生平活数据的标记,利便往后好计较。 (编辑:湖南网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |