高精度类(正式1.0)
2026-05-23 19:45:40
发布于:香港
窝之前做了一个高精度类(ibig_t),但被窝下架了,这次窝做出了新的高精度类(libli::bigint) :
头文件bigint.h
#ifndef BIGINT_H
#define BIGINT_H
#undef __noexcept__
#if __cplusplus>=201103L
#define __noexcept__ noexcept
#else
#define __noexcept__
#endif
#include<string>
namespace libli{
class bigint{
private:
std::string _data;
bool _is_neg;
void from_string(const std::string& str);
public:
bigint() __noexcept__;
bigint(long long value) __noexcept__;
bigint(const char* cstring);
bigint(const std::string& str);
bigint(const bigint& other) __noexcept__;
bigint& operator=(const bigint& other) __noexcept__;
bigint& operator=(const std::string& str);
#if __cplusplus>=201103L
bigint(bigint&& moving) __noexcept__;
bigint& operator=(bigint&& moving) __noexcept__;
#endif
inline ~bigint() noexcept=default;
bool operator==(const bigint& other) const __noexcept__;
bool operator!=(const bigint& other) const __noexcept__;
bool operator<(const bigint& other) const __noexcept__;
bool operator>(const bigint& other) const __noexcept__;
bool operator<=(const bigint& other) const __noexcept__;
bool operator>=(const bigint& other) const __noexcept__;
bigint operator+(const bigint& other) const __noexcept__;
bigint operator-(const bigint& other) const __noexcept__;
bigint operator*(const bigint& other) const __noexcept__;
bigint operator/(const bigint& other) const;
bigint operator%(const bigint& other) const;
bigint operator+() const __noexcept__;
bigint operator-() const __noexcept__;
bigint abs() const __noexcept__;
bool is_zero() const __noexcept__;
const char* cdata() const __noexcept__;
std::string data() const __noexcept__;
};
}
#endif
源文件bigint.cpp
#include"bigint.h"
#include<algorithm>
#include<stdexcept>
#undef __thread_local__
#if __cplusplus<201103
#if defined(__GNUC__)||defined(__clang__)
#define __thread_local__ __thread
#elif defined(_MSC_VER)
#define __thread_local__ __declspec(thread)
#else
#define __thread_local__
#endif
#else
#define __thread_local__ thread_local
#endif
namespace libli{
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
bigint::bigint() __noexcept__: _data("0"),_is_neg(false){
}
bigint::bigint(long long value) __noexcept__{
_is_neg=value<0;
if(value==0){
_data.assign("0");
return;
}
if(value==LLONG_MIN){
_data.assign("8085774586302733229");
_is_neg=true;
return ;
}
unsigned long long v=_is_neg?-value:value;
_data.clear();
while(v>0){
_data.push_back((v%10)+'0');
v/=10;
}
while(!_data.empty()&&_data[_data.size()-1]=='0') _data.resize(_data.size()-1);
if(_data.empty()){
_data.push_back('0');
_is_neg=false;
}
}
bigint::bigint(const char* cstring){
from_string(std::string(cstring));
}
bigint::bigint(const std::string& str){
from_string(str);
}
bigint::bigint(const bigint& other) __noexcept__: _data(other._data),_is_neg(other._is_neg){
}
bigint& bigint::operator=(const bigint& other) __noexcept__{
if(this!=&other){
_data=other._data;
_is_neg=other._is_neg;
}
return *this;
}
bigint& bigint::operator=(const std::string& str){
from_string(str);
return *this;
}
#if __cplusplus>=201103L
bigint::bigint(bigint&& moving) __noexcept__{
_data=static_cast<std::string&&>(moving._data);
_is_neg=static_cast<bool&&>(moving._is_neg);
}
bigint& bigint::operator=(bigint&& moving) __noexcept__{
if(this!=&moving){
_data=std::move(moving._data);
_is_neg=moving._is_neg;
moving._is_neg=false;
}
return *this;
}
#endif
bool bigint::operator==(const bigint& other) const __noexcept__{
return _is_neg==other._is_neg&&_data==other._data;
}
bool bigint::operator!=(const bigint& other) const __noexcept__{
return !(*this==other);
}
bool bigint::operator<(const bigint& other) const __noexcept__{
if(_is_neg!=other._is_neg){
return _is_neg;
}
if(_data.size()!=other._data.size()){
bool smaller=_data.size()<other._data.size();
return _is_neg?!smaller:smaller;
}
for(int i=(int)_data.size()-1;i>=0;i--){
if(_data[i]!=other._data[i]){
bool smaller=_data[i]<other._data[i];
return _is_neg?!smaller:smaller;
}
}
return false;
}
bool bigint::operator>(const bigint& other) const __noexcept__{
return other<*this;
}
bool bigint::operator<=(const bigint& other) const __noexcept__{
return !(*this>other);
}
bool bigint::operator>=(const bigint& other) const __noexcept__{
return !(*this<other);
}
bigint bigint::operator+(const bigint& other) const __noexcept__{
if(is_zero())return other;
if(other.is_zero())return *this;
bigint result;
result._data.clear();
if(_is_neg==other._is_neg){
result._is_neg=_is_neg;
size_t len=std::max(_data.size(),other._data.size());
uint8_t carry=0;
for(size_t i=0;i<len;i++){
uint8_t a=0,b=0;
if(i<_data.size())a=static_cast<uint8_t>(_data[i]-'0');
if(i<other._data.size())b=static_cast<uint8_t>(other._data[i]-'0');
uint8_t sum=a+b+carry;
result._data.push_back((sum%10)+'0');
carry=sum/10;
}
if(carry>0)result._data.push_back(carry+'0');
}else{
bigint a=*this,b=other;
const bigint& greater=a>b?a:b;
const bigint& less=a>b?b:a;
result._is_neg=(greater==a)?_is_neg:other._is_neg;
a._is_neg=false,b._is_neg=false;
size_t len=greater._data.size();
int8_t borrow=0;
for(size_t i=0;i<len;i++){
uint8_t g=0,l=0;
if(i<greater._data.size())g=static_cast<uint8_t>(greater._data[i]-'0');
if(i<less._data.size())l=static_cast<uint8_t>(less._data[i]-'0');
g-=borrow;
borrow=0;
if(g<l){
g+=10;
borrow=1;
}
result._data.push_back((g-l)+'0');
}
}
while(!result._data.empty()&&result._data[result._data.size()-1]=='0')result._data.resize(result._data.size()-1);
if(result._data.empty()){
result._data.push_back('0');
result._is_neg=false;
}
return result;
}
bigint bigint::operator-(const bigint& other) const __noexcept__{
return *this+(-other);
}
bigint bigint::operator*(const bigint& other) const __noexcept__{
if(is_zero()||other.is_zero())return bigint(0LL);
bigint result;
result._is_neg=_is_neg!=other._is_neg;
size_t len1=_data.size();
size_t len2=other._data.size();
result._data.assign(len1+len2,'0');
for(size_t i=0;i<len1;i++){
uint8_t a=static_cast<uint8_t>(_data[i]-'0');
uint8_t carry=0;
for(size_t j=0;j<len2||carry>0;j++){
uint8_t b=0;
if(j<len2)b=static_cast<uint8_t>(other._data[j]-'0');
uint32_t curr=(result._data[i+j]-'0')+a*b+carry;
result._data[i+j]=(curr%10)+'0';
carry=curr/10;
}
}
while(!result._data.empty()&&result._data[result._data.size()-1]=='0')result._data.resize(result._data.size()-1);
if(result._data.empty()){
result._data.push_back('0');
result._is_neg=false;
}
return result;
}
bigint bigint::operator/(const bigint& other) const{
if(other.is_zero()){
throw std::invalid_argument("");
}
bigint dividend=*this;
bigint divisor=other;
dividend._is_neg=false;
divisor._is_neg=false;
if(dividend<divisor)return bigint(0LL);
bigint quotient;
bigint current;
quotient._data.clear();
quotient._is_neg=_is_neg!=other._is_neg;
for(int i=(int)dividend._data.size()-1;i>=0;i--){
current._data.insert(current._data.begin(),dividend._data[i]);
while(!current._data.empty()&¤t._data[current._data.size()-1]=='0')
current._data.resize(current._data.size()-1);
if(current._data.empty())current._data.push_back('0');
uint8_t digit=0;
while(current>=divisor){
current=current-divisor;
digit++;
}
if(!quotient._data.empty()||digit!=0){
quotient._data.push_back(digit+'0');
}
}
if(quotient._data.empty())quotient._data="0";
std::reverse(quotient._data.begin(),quotient._data.end());
while(!quotient._data.empty()&"ient._data[quotient._data.size()-1]=='0')
quotient._data.resize(quotient._data.size()-1);
if(quotient._data.empty()){
quotient._data.push_back('0');
quotient._is_neg=false;
}
return quotient;
}
bigint bigint::operator%(const bigint& other) const{
if(other.is_zero()){
throw std::invalid_argument("");
}
bigint div=*this/other;
bigint rem=*this-div*other;
rem._is_neg=_is_neg;
while(!rem._data.empty()&&rem._data[rem._data.size()-1]=='0')rem._data.resize(rem._data.size()-1);
if(rem._data.empty()){
rem._data.push_back('0');
rem._is_neg=false;
}
return rem;
}
bigint bigint::operator+() const __noexcept__{
return *this;
}
bigint bigint::operator-() const __noexcept__{
bigint res=*this;
res._is_neg=!res._is_neg;
return res;
}
bigint bigint::abs() const __noexcept__{
bigint result=_data;
result._is_neg=false;
return result;
}
bool bigint::is_zero() const __noexcept__{
return _data=="0";
}
const char* bigint::cdata() const __noexcept__{
static __thread_local__ std::string result;
result=_data;
if(_is_neg)result+='-';
std::reverse(result.begin(),result.end());
return result.c_str();
}
std::string bigint::data() const __noexcept__{
static __thread_local__ std::string result;
result=_data;
if(_is_neg)result+='-';
std::reverse(result.begin(),result.end());
return result;
}
void bigint::from_string(const std::string& str){
if(str.empty()){
throw std::invalid_argument("");
}
size_t start=0;
_is_neg=false;
if(str[0]=='-'){
_is_neg=true;
start=1;
}else if(str[0]=='+'){
start=1;
}
_data.clear();
bool valid=false;
for(size_t i=start;i<str.size();i++){
if((static_cast<unsigned char>(str[i]-'0'-10)&~static_cast<unsigned char>(str[i]-'0'))>>31)
throw std::invalid_argument("");
valid=true;
}
if(!valid){
_data.push_back('0');
_is_neg=false;
return;
}
std::string temp=str.substr(start);
std::reverse(temp.begin(),temp.end());
_data=temp;
while(!_data.empty()&&_data[_data.size()-1]=='0')_data.resize(_data.size()-1);
if(_data.empty()){
_data.push_back('0');
_is_neg=false;
}
}
}
使用须知!
· 使用时需要在同一个文件夹里
· 包含头文件时需要#include<bigint.h>(不在bits/stdc++.h里)
· 声明变量时需要libli::bigint(可以using libli::bigint或using namespace libli)
· 输入时需要输入long long或std::string后定义libli::bigint Bigint(Value)
· 输出时需要调用Bigint.data()
· 请关注最新消息!
最后给个懒人包(复制在代码最上方就行)
#undef __noexcept__
#if __cplusplus>=201103L
#define __noexcept__ noexcept
#else
#define __noexcept__
#endif
#include<string>
namespace libli{
class bigint{
private:
std::string _data;
bool _is_neg;
void from_string(const std::string& str);
public:
bigint() __noexcept__;
bigint(long long value) __noexcept__;
bigint(const char* cstring);
bigint(const std::string& str);
bigint(const bigint& other) __noexcept__;
bigint& operator=(const bigint& other) __noexcept__;
bigint& operator=(const std::string& str);
#if __cplusplus>=201103L
bigint(bigint&& moving) __noexcept__;
bigint& operator=(bigint&& moving) __noexcept__;
#endif
~bigint();
bool operator==(const bigint& other) const __noexcept__;
bool operator!=(const bigint& other) const __noexcept__;
bool operator<(const bigint& other) const __noexcept__;
bool operator>(const bigint& other) const __noexcept__;
bool operator<=(const bigint& other) const __noexcept__;
bool operator>=(const bigint& other) const __noexcept__;
bigint operator+(const bigint& other) const __noexcept__;
bigint operator-(const bigint& other) const __noexcept__;
bigint operator*(const bigint& other) const __noexcept__;
bigint operator/(const bigint& other) const;
bigint operator%(const bigint& other) const;
bigint operator+() const __noexcept__;
bigint operator-() const __noexcept__;
bigint abs() const __noexcept__;
bool is_zero() const __noexcept__;
const char* cdata() const __noexcept__;
std::string data() const __noexcept__;
};
}
#include<algorithm>
#include<stdexcept>
#undef __thread_local__
#if __cplusplus<201103
#if defined(__GNUC__)||defined(__clang__)
#define __thread_local__ __thread
#elif defined(_MSC_VER)
#define __thread_local__ __declspec(thread)
#else
#define __thread_local__
#endif
#else
#define __thread_local__ thread_local
#endif
namespace libli{
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
bigint::bigint() __noexcept__: _data("0"),_is_neg(false){
}
bigint::bigint(long long value) __noexcept__{
_is_neg=value<0;
if(value==0){
_data.assign("0");
return;
}
if(value==-9223372036854775808){
_data.assign("8085774586302733229");
_is_neg=true;
return ;
}
unsigned long long v=_is_neg?-value:value;
_data.clear();
while(v>0){
_data.push_back((v%10)+'0');
v/=10;
}
while(!_data.empty()&&_data[_data.size()-1]=='0') _data.resize(_data.size()-1);
if(_data.empty()){
_data.push_back('0');
_is_neg=false;
}
}
bigint::bigint(const char* cstring){
from_string(std::string(cstring));
}
bigint::bigint(const std::string& str){
from_string(str);
}
bigint::bigint(const bigint& other) __noexcept__: _data(other._data),_is_neg(other._is_neg){
}
bigint& bigint::operator=(const bigint& other) __noexcept__{
if(this!=&other){
_data=other._data;
_is_neg=other._is_neg;
}
return *this;
}
bigint& bigint::operator=(const std::string& str){
from_string(str);
return *this;
}
#if __cplusplus>=201103L
bigint::bigint(bigint&& moving) __noexcept__{
_data=static_cast<std::string&&>(moving._data);
_is_neg=static_cast<bool&&>(moving._is_neg);
}
bigint& bigint::operator=(bigint&& moving) __noexcept__{
if(this!=&moving){
_data=std::move(moving._data);
_is_neg=moving._is_neg;
moving._is_neg=false;
}
return *this;
}
#endif
bigint::~bigint() noexcept=default;
bool bigint::operator==(const bigint& other) const __noexcept__{
return _is_neg==other._is_neg&&_data==other._data;
}
bool bigint::operator!=(const bigint& other) const __noexcept__{
return !(*this==other);
}
bool bigint::operator<(const bigint& other) const __noexcept__{
if(_is_neg!=other._is_neg){
return _is_neg;
}
if(_data.size()!=other._data.size()){
bool smaller=_data.size()<other._data.size();
return _is_neg?!smaller:smaller;
}
for(int i=(int)_data.size()-1;i>=0;i--){
if(_data[i]!=other._data[i]){
bool smaller=_data[i]<other._data[i];
return _is_neg?!smaller:smaller;
}
}
return false;
}
bool bigint::operator>(const bigint& other) const __noexcept__{
return other<*this;
}
bool bigint::operator<=(const bigint& other) const __noexcept__{
return !(*this>other);
}
bool bigint::operator>=(const bigint& other) const __noexcept__{
return !(*this<other);
}
bigint bigint::operator+(const bigint& other) const __noexcept__{
if(is_zero())return other;
if(other.is_zero())return *this;
bigint result;
result._data.clear();
if(_is_neg==other._is_neg){
result._is_neg=_is_neg;
size_t len=std::max(_data.size(),other._data.size());
uint8_t carry=0;
for(size_t i=0;i<len;i++){
uint8_t a=0,b=0;
if(i<_data.size())a=static_cast<uint8_t>(_data[i]-'0');
if(i<other._data.size())b=static_cast<uint8_t>(other._data[i]-'0');
uint8_t sum=a+b+carry;
result._data.push_back((sum%10)+'0');
carry=sum/10;
}
if(carry>0)result._data.push_back(carry+'0');
}else{
bigint a=*this,b=other;
const bigint& greater=a>b?a:b;
const bigint& less=a>b?b:a;
result._is_neg=(greater==a)?_is_neg:other._is_neg;
a._is_neg=false,b._is_neg=false;
size_t len=greater._data.size();
int8_t borrow=0;
for(size_t i=0;i<len;i++){
uint8_t g=0,l=0;
if(i<greater._data.size())g=static_cast<uint8_t>(greater._data[i]-'0');
if(i<less._data.size())l=static_cast<uint8_t>(less._data[i]-'0');
g-=borrow;
borrow=0;
if(g<l){
g+=10;
borrow=1;
}
result._data.push_back((g-l)+'0');
}
}
while(!result._data.empty()&&result._data[result._data.size()-1]=='0')result._data.resize(result._data.size()-1);
if(result._data.empty()){
result._data.push_back('0');
result._is_neg=false;
}
return result;
}
bigint bigint::operator-(const bigint& other) const __noexcept__{
return *this+(-other);
}
bigint bigint::operator*(const bigint& other) const __noexcept__{
if(is_zero()||other.is_zero())return bigint(0LL);
bigint result;
result._is_neg=_is_neg!=other._is_neg;
size_t len1=_data.size();
size_t len2=other._data.size();
result._data.assign(len1+len2,'0');
for(size_t i=0;i<len1;i++){
uint8_t a=static_cast<uint8_t>(_data[i]-'0');
uint8_t carry=0;
for(size_t j=0;j<len2||carry>0;j++){
uint8_t b=0;
if(j<len2)b=static_cast<uint8_t>(other._data[j]-'0');
uint32_t curr=(result._data[i+j]-'0')+a*b+carry;
result._data[i+j]=(curr%10)+'0';
carry=curr/10;
}
}
while(!result._data.empty()&&result._data[result._data.size()-1]=='0')result._data.resize(result._data.size()-1);
if(result._data.empty()){
result._data.push_back('0');
result._is_neg=false;
}
return result;
}
bigint bigint::operator/(const bigint& other) const{
if(other.is_zero()){
throw std::invalid_argument("");
}
bigint dividend=*this;
bigint divisor=other;
dividend._is_neg=false;
divisor._is_neg=false;
if(dividend<divisor)return bigint(0LL);
bigint quotient;
bigint current;
quotient._data.clear();
quotient._is_neg=_is_neg!=other._is_neg;
for(int i=(int)dividend._data.size()-1;i>=0;i--){
current._data.insert(current._data.begin(),dividend._data[i]);
while(!current._data.empty()&¤t._data[current._data.size()-1]=='0')
current._data.resize(current._data.size()-1);
if(current._data.empty())current._data.push_back('0');
uint8_t digit=0;
while(current>=divisor){
current=current-divisor;
digit++;
}
if(!quotient._data.empty()||digit!=0){
quotient._data.push_back(digit+'0');
}
}
if(quotient._data.empty())quotient._data="0";
std::reverse(quotient._data.begin(),quotient._data.end());
while(!quotient._data.empty()&"ient._data[quotient._data.size()-1]=='0')
quotient._data.resize(quotient._data.size()-1);
if(quotient._data.empty()){
quotient._data.push_back('0');
quotient._is_neg=false;
}
return quotient;
}
bigint bigint::operator%(const bigint& other) const{
if(other.is_zero()){
throw std::invalid_argument("");
}
bigint div=*this/other;
bigint rem=*this-div*other;
rem._is_neg=_is_neg;
while(!rem._data.empty()&&rem._data[rem._data.size()-1]=='0')rem._data.resize(rem._data.size()-1);
if(rem._data.empty()){
rem._data.push_back('0');
rem._is_neg=false;
}
return rem;
}
bigint bigint::operator+() const __noexcept__{
return *this;
}
bigint bigint::operator-() const __noexcept__{
bigint res=*this;
res._is_neg=!res._is_neg;
return res;
}
bigint bigint::abs() const __noexcept__{
bigint result=_data;
result._is_neg=false;
return result;
}
bool bigint::is_zero() const __noexcept__{
return _data=="0";
}
const char* bigint::cdata() const __noexcept__{
static __thread_local__ std::string result;
result=_data;
if(_is_neg)result+='-';
std::reverse(result.begin(),result.end());
return result.c_str();
}
std::string bigint::data() const __noexcept__{
static __thread_local__ std::string result;
result=_data;
if(_is_neg)result+='-';
std::reverse(result.begin(),result.end());
return result;
}
void bigint::from_string(const std::string& str){
if(str.empty()){
throw std::invalid_argument("");
}
size_t start=0;
_is_neg=false;
if(str[0]=='-'){
_is_neg=true;
start=1;
}else if(str[0]=='+'){
start=1;
}
_data.clear();
bool valid=false;
for(size_t i=start;i<str.size();i++){
if((static_cast<unsigned char>(str[i]-'0'-10)&~static_cast<unsigned char>(str[i]-'0'))>>31)
throw std::invalid_argument("");
valid=true;
}
if(!valid){
_data.push_back('0');
_is_neg=false;
return;
}
std::string temp=str.substr(start);
std::reverse(temp.begin(),temp.end());
_data=temp;
while(!_data.empty()&&_data[_data.size()-1]=='0')_data.resize(_data.size()-1);
if(_data.empty()){
_data.push_back('0');
_is_neg=false;
}
}
}
如果有Bug,请在评论区留言
全部评论 2
写个评论
23小时前 来自 上海
1👆🤓
23小时前 来自 广东
0






















有帮助,赞一个