大整数又称为高精度整数,其含义就是用基本数据类型无法储存其精度的整数。
一、大整数的存储
很简单,使用数组即可。例如定义 int 型数组 d[1000],那么这个数组的每一位代表了存放整数的每一位。整数的高位储存在数组的高位,整数的低位储存在数组的低位。
而为了方便随时获取大整数的长度,一般都会定义一个 int 型变量 len 来记录其长度,结构体如下:
1 // 大整数 2 struct bign { 3 int d[1000]; 4 int len; 5 };
在定义结构体变量后,需要马上初始化结构体,加上“构造函数”,代码如下:
// 大整数 struct bign { int d[1000]; int len; bign() { // 构造函数 memset(d, 0, sizeof(d)); len = 0; } };
而输入大整数时,一般都是先用字符串读入,然后再把字符串另存为至 bign 结构体。由于使用 char 数组进行读入时,整数的高位会变成数组的低位,因此需要让字符串倒着赋给 d[] 数组:
1 // 将字符串另存至 bign 结构体 2 bign change(char str[]) { 3 bign a; 4 a.len = strlen(str); // bign 的长度就是数组的长度 5 int i; 6 for(i=0; i<a.len; ++i) { // 倒着赋值 7 a.d[i] = str[a.len-1-i] - '0'; 8 } 9 return a; 10 }
如果要比较两个 bign 变量的大小,规则也很简单:先判断两者的 len 的大小,如果不相等,则以长的为大;如果相等,则从高位到低位进行比较,直到出现某一位不等,就可以判断两个数的大小。代码如下:
1 // 比较两个大整数变量的大小 2 // a 大、相等、小分别返回 1、0、-1 3 int compare(bign a, bign b) { 4 if(a.len ? b.len) return 1; // a>b 5 else if(a.len < b.len) return -1; // a<b 6 else { 7 int i; 8 for(i=0; i<a.len; ++i) { // 从高位到低位比较 9 if(a.d[i] > b.d[i]) return 1; // a>b 10 else if(a.d[i] < b.d[i]) return -1; // a<b 11 } 12 return 0; // 两者相等 13 } 14 }
二、大整数的四则运算
1. 高精度加法
容易得到对其中一位进行加法的步骤:将该位上的两个数字与进位相加,得到的结果取个位数作为该位结果,取十位数作为新的进位。代码如下:
1 // 高精度加法 2 bign add(bign a, bign b) { 3 bign c; 4 int carry = 0; // 进位 5 int i; 6 for(i=0; i<a.len || i<b.len; ++i) { // 以较长的为界限 7 int temp = a.d[i] + b.d[i] + carry; // 其中一位相加 8 c.d[c.len++] = temp%10; // 取个位 9 carry = temp/10; // 新的进位 10 } 11 if(carry != 0) { // 有进位 12 c.d[c.len++] = carry; 13 } 14 return c; 15 }
测试一下加法代码,以下为 C 代码:
1 /* 2 大整数运算 3 */ 4 5 #include <stdio.h> 6 #include <string.h> 7 #include <math.h> 8 #include <stdlib.h> 9 #include <time.h> 10 #include <stdbool.h> 11 12 // 大整数 13 typedef struct{ 14 int d[1000]; 15 int len; 16 // C 中 struct 不能有函数 17 /*bign() { // 构造函数 18 memset(d, 0, sizeof(d)); 19 len = 0; 20 }*/ 21 } bign; 22 23 // 大整数初始化 24 bign init() { 25 bign temp = { {0},0 }; 26 return temp; 27 } 28 29 // 将字符串另存至 bign 结构体 30 bign change(char str[]) { 31 bign a = init(); 32 a.len = strlen(str); // bign 的长度就是数组的长度 33 int i; 34 for(i=0; i<a.len; ++i) { // 倒着赋值 35 a.d[i] = str[a.len-1-i] - '0'; 36 } 37 return a; 38 } 39 40 // 比较两个大整数变量的大小 41 // a 大、相等、小分别返回 1、0、-1 42 int compare(bign a, bign b) { 43 if(a.len > b.len) return 1; // a>b 44 else if(a.len < b.len) return -1; // a<b 45 else { 46 int i; 47 for(i=0; i<a.len; ++i) { // 从高位到低位比较 48 if(a.d[i] > b.d[i]) return 1; // a>b 49 else if(a.d[i] < b.d[i]) return -1; // a<b 50 } 51 return 0; // 两者相等 52 } 53 } 54 55 // 高精度加法 56 bign add(bign a, bign b) { 57 bign c = init(); 58 int carry = 0; // 进位 59 int i; 60 for(i=0; i<a.len || i<b.len; ++i) { // 以较长的为界限 61 int temp = a.d[i] + b.d[i] + carry; // 其中一位相加 62 c.d[c.len++] = temp%10; // 取个位 63 carry = temp/10; // 新的进位 64 } 65 if(carry != 0) { // 有进位 66 c.d[c.len++] = carry; 67 } 68 return c; 69 } 70 71 // 输出大整数 72 void print(bign a) { 73 int i; 74 for(i=a.len-1; i>=0; --i) { 75 printf("%d", a.d[i]); 76 } 77 printf("\n"); 78 } 79 80 int main() { 81 char str1[1000], str2[1000]; 82 scanf("%s%s", str1, str2); 83 bign a = change(str1); 84 bign b = change(str2); 85 print(add(a, b)); 86 87 return 0; 88 }