一.為什仫要實現大數運算?
我們知道在數學領域中,數值的大小是沒有上限的,但是計算機中,由於字長的限制,計算機所能表示的範圍是有限的,當我們在實際的應用中進行大量的資料處理的時候,會發現參與運算的數往往超過計算機的基本資料型別的表示範圍。假設乙個資料的型別是long long那仫它最多可表示的資料是8個位元組,一但超出這個範圍,就無法用程式語言的內建型別儲存,因此就產生了大數運算這種方法。
二.大數運算是如何實現的?
1).將大數轉換成字串儲存在陣列裡面,然後再對每一位做單獨的加減乘除運算。
2).設計乙個大數的資料型別,讓這種資料型別既可以進行大數的運算,也可以支援沒有超出內建型別範圍的數的運算。
3).當然了如果資料本身就沒有超出範圍當然就不需要每乙個位都計算啦!如果要運算的數可以用內建型別表示,且計算結果也可以用內建型別表示,那麼我們就直接進行運算。如果要運算的數超出範圍,或者計算結果超出範圍,那麼我們就使用大數的運算法則。
三.**實現
1).首先需要的是將乙個大數儲存起來,當然要處理不合理的情況啦,感覺有點模擬atoi的感覺!!!
@空串
@是否存在空白字元,如果全部是空白字元
@是否存在』+』或者是』-『號
@是否存在字元』0』,如果全部是字元』0』
@是否存在非數字字元
bigdata::bigdata(const std::string& str)
:_value(0)
,_strdata("+0")
//可能乙個串全部是空格
if(*pdata == '\0')
return ;
//確定符號位
char sign=*pdata;
if(*pdata == '+' || *pdata == '-')
pdata++;
else
if(isdigit(*pdata))
sign='+';
else
return ;
//可能前面存在字元0
while(*pdata == '0')
//全0
if(*pdata == '\0')
return ;
_strdata.resize(strlen(pdata)+1);
_strdata[0]=sign; //第一位存放符號位
size_t count=1;
//如果是數字則在_value和_strdata中都儲存乙份
while(*pdata >= '0' && *pdata <= '9')
if(sign == '-')
_value=0-_value;
_strdata.resize(count); //縮小當前的空間大小
}
2).判斷資料是否溢位
如果資料的大小在long long所能表示的8個位元組的範圍內則可以直接計算,如果超出了呢?則需要自定義處理,如何判斷是否超出?
//判斷資料是否溢位
bool bigdata::isint64overflow(const
string& strdata)
return
true;
}
3).大數運算
bigdata bigdata::operator+(const bigdata& b)
else
if(_strdata[0] == '+' && maxvalue-_value >= b._value || \
_strdata[0] == '-' && minvalue-_value <= b._value)
}if(_strdata[0] == b._strdata[0]) //同號相加,呼叫add函式
else
}bigdata bigdata::operator-(const bigdata& b)
bigdata bigdata::operator*(const bigdata& b)
else
//異號
}//判斷是否存在正負1的情況
if(_strdata[0] == '+1')
return bigdata(b._strdata);
if(b._strdata[0] == '+1')
return bigdata(_strdata);
if(_strdata[0] == '-1')
if(b._strdata[0] == '-1')
return bigdata(mul(_strdata,b._strdata));
}bigdata bigdata::add(string left,string right)
string result;
result.resize(leftsize+1);
result[0]=left[0];//儲存符號
char step=0; //儲存進製
for(size_t index=1;indexchar ret=left[leftsize-index]-'0';
if(index < rightsize)
ret=ret+right[rightsize-index]-'0';
ret += step;
step=ret/10; //更新進製的值,取較高位
result[leftsize+1-index]=ret%10+'0';
}result[1]=step+'0'; //相加到最後一位也有可能產生進製
return result;
}bigdata bigdata::sub(string left,string right)
string result;
result.resize(leftsize);
result[0]=sign;
for(size_t index=1;indexchar ret=left[leftsize-index]-'0';
if(index < rightsize)
ret=ret-(right[rightsize-index]-'0');
if(ret < 0) //減出的結果為負數,從高位借位,以1當10
result[leftsize-index]=ret+'0';
}return result;
}bigdata bigdata::mul(string left,string right)
string result;
result.resize(leftsize+rightsize-1,'0');
result[0]=sign;
char step=0; //儲存進製
char ioffset=0; //儲存偏移量
//乘法的原理是獲取左邊的一位資料分別乘以另乙個數的每一位,所以用到兩個迴圈
for(size_t i=1;ichar tmp=left[leftsize-i]-'0';
if(tmp == 0) //過濾掉中間的0
step=0; //進製的值歸零
for(size_t j=1;jchar ret=tmp*(right[rightsize-j]-'0');
ret += step;
ret = ret + (result[leftsize+rightsize-1-j-ioffset]-'0');
step=ret/10; //跟新進製的值
result[leftsize+rightsize-1-j-ioffset]=ret%10+'0';
}result[leftsize-ioffset-1] = step+'0';
ioffset++;
}return result;
}
在大數運算裡面我覺得除法是最不好理解的,下面是我畫的乙個除法的原理圖:
由上圖可知,我用了乙個指標pleft+datalen來查詢乙個能夠除過除數的數,使用迴圈遞減的方法來確定商。
商*除數+餘數=最終結果,來判斷計算結果是否正確。
bigdata bigdata::div(string left,string right)
if(!isleftlarge(pleft,datalen,pright,rightsize-1))
else
}return tmp;
}//判斷是否左邊大
bool bigdata::isleftlarge(const char *pleft,const size_t datalen,const char *pright,const size_t rightsize)
return
false;
}char bigdata::subloop(char*& pleft, size_t& datalen, const char *pright,const size_t rightsize)
if (ret < 0) //向高位借位,以1當10
pleft[datalen-index]=ret+'0';
}count++;
while (*pleft == '0' && datalen > 0) //跳過高位的0
}return
count;
}
簡單計算器模擬
雖然打個簡單計算器不算難事,但是模擬始終算一關,不能忽視基礎。本程式不適用以下情況 表示式中帶空格 表示式中帶括號 僅能進行四則運算,結果限制在int型 include using namespace std intlevel char x intcalculate string s if q1.e...
Problem 模擬簡單計算器
time limit 1 sec memory limit 64 mb submit 4325 solved 1524 程式模擬簡單運算器的工作 輸入乙個算式 沒有空格 遇到 號說明輸入結束,輸出結果。假設計算器只能進行加 減 乘 除運算,運算數和結果都是整數,4種運算子的優先順序相同,按從左到右的...
簡單計算器的實現
計算器 問題描述 輸入乙個簡單四則運算表示式字串,計算該表示式的值 注 1 表示式只含 四則運算符 2 表示式數值只包含整數 0 9 每個運算元可以是多位,且不會出現0作為除數的情況 3 要考慮加減乘除按通常四則運算規定的計算優先順序 4 除法用整數除法,即僅保留除法運算結果的整數部分。比如80 3...