C++實現高精度大整數(大數)的四則運算
阿新 • • 發佈:2019-01-01
為了便於大整數的運算,我們首先定義一個結構體,用於儲存大整數。
struct bign{
int d[1000];
int len;
//下面定義建構函式,用來初始化!
bign(){
memset(d,0,sizeof(d));
len=0;
}
};
其中,bign(){}函式沒有任何返回值,作為bign結構體的解構函式,用於對定義的bign進行初始化。
一般來說,大整數一般是使用字串輸入的,下面將字串儲存的大整數存放在結構體中:
bign change(char str[]){ bign a; a.len=strlen(str); for(int i=0;i<a.len;i++){ a.d[i]=str[a.len-i-1]-'0';//這裡把大整數的地位切換為高位 } return a; }
返回的是bign型別的,也就是將char型別轉換為了我剛才定義的大整數型別。
對於演算法競賽初級來說,比較兩個大整數的大小的題目也是非常常見的,下面為比較大小函式。
int compare(bign a,bign b){ if(a.len>b.len)return 1;//a大於b else if(a.len<b.len)return -1;//a<b else{ for(int i=a.len-1;i>=0;i++){ if(a.d[i]>b.d[i])return 1; else if(a.d[i]<b.d[i])return -1; } return 0;//兩個數相等 } }
下面是加法法則,其演算法與小學時的加法運算相同!!!和小學的演算法相同。。。
bign add(bign a,bign b){
bign c;
int carry=0;//這裡的carry表示進位
for(int i=0;i<a.len||i<b.len;i++){
int temp=a.d[i]+b.d[i]+carry;
c.d[c.len++]=temp%10;
carry=temp/10;
}
if(carry!=0){//如果最後一位的進位不為0,直接付給結果的最高位
c.d[c.len++] =carry;
}
return c;
}
//值得注意的是,上面的演算法的條件都是非負整數,那麼如果有一個數是負數怎麼辦呢????
//如果有一個數字為負數,我們可以使用高精度減法
下面介紹高精度減法
bign sub(bign a,bign b){
bign c;
for(int i=0;i<a.len||i<b.len;i++){
if(a.d[i]<b.d[i]) {//如果不夠減法,則向高位借位
if(a.d[i+1]>0){
a.d[i+1]--;
a.d[i]+=10;
}
}
c.d[c.len++]=a.d[i]-b.d[i];
}
while(c.len-1>=1&&c.d[c.len-1]==0){
c.len--;
}//去除高位為0的!同時保留一個最低位
return c;
}
高精度與低精度乘法運算規則
bign multi(bign a,int b){
bign c;
int carry=0;
for(int i=0;i<a.len;i++){
int temp=a.d[i]*b+carry;
c.d[c.len++]=temp%10;
carry=temp/10;
}
while(carry!=0)
{
c.d[c.len++]=carry%10;
carry/=10;
}
return c;
}
高精度與低精度的除法
bign divide(bign a,int b,int &r){//r為餘數,這裡表示為引用
bign c;
c.len=a.len;
for(int i=a.len-1;i>=0;i--){
r=r*10+a.d[i];
if(r<b) c.d[i]=0;
else{
c.d[i]=r/b;
r=r%b;
}
}
while(c.len-1>=1&&c.d[c.len-1]==0){
c.len--;
}
return c;
}
列印結果!
void print(bign a){
for(int i=a.len-1;i>=0;i--)
{
printf("%d",a.d[i]);
}
}
主函式,這裡只調用兩個數 相加的情況
int main(){
char str1[1000],str2[1000];
scanf("%s%s",str1,str2);
bign a=change(str1);
bign b=change(str2);
print(add(a,b));
return 0;
}
完整程式碼:
#include <stdio.h>
#include<iostream>
#include <string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
//基於C++的大整數運算
//首先,為了方便後面運算,我們先定義一個結構體
struct bign{
int d[1000];
int len;
//下面定義建構函式,用來初始化!
bign(){
memset(d,0,sizeof(d));
len=0;
}
};
//一般來說,大整數一般是使用字串輸入的,下面將字串儲存的大整數
//存放在結構體中
bign change(char str[]){
bign a;
a.len=strlen(str);
for(int i=0;i<a.len;i++){
a.d[i]=str[a.len-i-1]-'0';//這裡把大整數的地位切換為高位
}
return a;
}
//比較兩個大整數的大小
int compare(bign a,bign b){
if(a.len>b.len)return 1;//a大於b
else if(a.len<b.len)return -1;//a<b
else{
for(int i=a.len-1;i>=0;i++){
if(a.d[i]>b.d[i])return 1;
else if(a.d[i]<b.d[i])return -1;
}
return 0;//兩個數相等
}
}
//下面是大數的四則運演算法則
bign add(bign a,bign b){
bign c;
int carry=0;//這裡的carry表示進位
for(int i=0;i<a.len||i<b.len;i++){
int temp=a.d[i]+b.d[i]+carry;
c.d[c.len++]=temp%10;
carry=temp/10;
}
if(carry!=0){//如果最後一位的進位不為0,直接付給結果的最高位
c.d[c.len++] =carry;
}
return c;
}
//值得注意的是,上面的演算法的條件都是非負整數,那麼如果有一個數是負數怎麼辦呢????
//如果有一個數字為負數,我們可以使用高精度減法
bign sub(bign a,bign b){
bign c;
for(int i=0;i<a.len||i<b.len;i++){
if(a.d[i]<b.d[i]) {//如果不夠減法,則向高位借位
if(a.d[i+1]>0){
a.d[i+1]--;
a.d[i]+=10;
}
}
c.d[c.len++]=a.d[i]-b.d[i];
}
while(c.len-1>=1&&c.d[c.len-1]==0){
c.len--;
}//去除高位為0的!同時保留一個最低位
return c;
}
//高精度的乘法運算規則
bign multi(bign a,int b){
bign c;
int carry=0;
for(int i=0;i<a.len;i++){
int temp=a.d[i]*b+carry;
c.d[c.len++]=temp%10;
carry=temp/10;
}
while(carry!=0)
{
c.d[c.len++]=carry%10;
carry/=10;
}
return c;
}
//高精度與低精度的除法
bign divide(bign a,int b,int &r){//r為餘數,這裡表示為引用
bign c;
c.len=a.len;
for(int i=a.len-1;i>=0;i--){
r=r*10+a.d[i];
if(r<b) c.d[i]=0;
else{
c.d[i]=r/b;
r=r%b;
}
}
while(c.len-1>=1&&c.d[c.len-1]==0){
c.len--;
}
return c;
}
void print(bign a){
for(int i=a.len-1;i>=0;i--)
{
printf("%d",a.d[i]);
}
}
int main(){
char str1[1000],str2[1000];
scanf("%s%s",str1,str2);
bign a=change(str1);
bign b=change(str2);
print(add(a,b));
return 0;
}
以上內容的參考資料:《演算法筆記》——第五章入門篇(3)——數學問題
相關練習題:
PAT:https://www.patest.cn/contests/pat-b-practise/1017
時間限制 100 ms記憶體限制 65536 kB
程式碼長度限制 8000 B
判題程式 Standard 作者 CHEN, Yue
本題要求計算A/B,其中A是不超過1000位的正整數,B是1位正整數。你需要輸出商數Q和餘數R,使得A = B * Q + R成立。
輸入格式:
輸入在1行中依次給出A和B,中間以1空格分隔。
輸出格式:
在1行中依次輸出Q和R,中間以1空格分隔。
輸入樣例:123456789050987654321 7輸出樣例:
17636684150141093474 3直接使用上面的演算法
AC程式碼:
#include <stdio.h>
#include<iostream>
#include <string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
//基於C++的大整數運算
//首先,為了方便後面運算,我們先定義一個結構體
struct bign{
int d[1000];
int len;
//下面定義建構函式,用來初始化!
bign(){
memset(d,0,sizeof(d));
len=0;
}
};
//一般來說,大整數一般是使用字串輸入的,下面將字串儲存的大整數
//存放在結構體中
bign change(char str[]){
bign a;
a.len=strlen(str);
for(int i=0;i<a.len;i++){
a.d[i]=str[a.len-i-1]-'0';//這裡把大整數的地位切換為高位
}
return a;
}
//高精度與低精度的除法
bign divide(bign a,int b,int &r){//r為餘數,這裡表示為引用
bign c;
c.len=a.len;
for(int i=a.len-1;i>=0;i--){
r=r*10+a.d[i];
if(r<b) c.d[i]=0;
else{
c.d[i]=r/b;
r=r%b;
}
}
while(c.len-1>=1&&c.d[c.len-1]==0){
c.len--;
}
return c;
}
void print(bign a){
for(int i=a.len-1;i>=0;i--)
{
printf("%d",a.d[i]);
}
}
int main(){
char str1[1000];
int b;
scanf("%s%d",str1,&b);
bign a=change(str1);
int r=0;
print(divide(a,b,r));
printf(" %d",r);
return 0;
}
以上內容原創,轉載請註明出處!