7-2 BigInt1.c
1 #include <stdio.h> 2 #include <string.h> 3 typedef struct bigint 4 { 5 char *num; //指向长整数数组(序号0中保存着最低位) 6 char minus; //符号(1表示正数,-1表示负数) 7 int digit; //保存该数的位数(实际位数) 8 }BIGINT, *pBIGINT; 9 void BigIntTrans(pBIGINT num); //字符串转数字 10 void BigIntMul(pBIGINT num1, pBIGINT num2, pBIGINT result); //乘法函数 11 void BigIntAdd1(pBIGINT num1, pBIGINT num2, pBIGINT result); //同号数相加 12 void BigIntAdd(pBIGINT num1, pBIGINT num2, pBIGINT result); //加法函数 13 void BigIntSub1(pBIGINT num1, pBIGINT num2, pBIGINT result); //异号相减函数 14 void BigIntSub(pBIGINT num1, pBIGINT num2, pBIGINT result); //减法函数 15 void BigIntDiv(pBIGINT num1, pBIGINT num2, pBIGINT result, pBIGINT residue); //除法函数 16 void BigIntPrint(pBIGINT result); //输出大整数 17 int BigIntEqual(pBIGINT num1, pBIGINT num2); //两数大小比较 18 19 void BigIntTrim(pBIGINT num1) //整理大整数,去掉前面多余的0,并使调整其位数 20 { 21 int i; 22 for (i = num1->digit - 1; i >= 0; i--) 23 { 24 if (num1->num[i] != 0) 25 break; 26 } 27 if (i < 0) //若余数全部为0 28 { 29 num1->digit = 1; //设置余数位数为1 30 num1->num[0] = 0; 31 } else 32 num1->digit = i + 1; //余数位数 33 } 34 void BigIntTrans(pBIGINT num1) //将字符串转为数字表示 35 { 36 char *temp; //临时数组 37 int i, k, len; 38 len = strlen(num1->num); //字符串长度 39 if (!(temp = (char *) malloc(sizeof(char) * len))) //分配内存 40 { 41 printf("内存分配失败!\n"); 42 exit(0); 43 } 44 i = 0; 45 num1->minus = 1; //保存为正数 46 if (num1->num[0] == ‘-‘) //判断是否为负数 47 { 48 num1->minus = -1; //保存为负数 49 i++; 50 } 51 k = 0; //数字位数计数器 52 while (num1->num[i] != ‘\0‘) //字符串未结束 53 { 54 if (num1->num[i] >= ‘0‘ && num1->num[i] <= ‘9‘) //为数字0~9 55 { 56 temp[k] = num1->num[i] - ‘0‘; //将ASCII码转换为对应数字 57 k++; 58 } 59 i++; 60 } 61 62 for (i = 0; i < num1->digit; i++) //清空数组各元素 63 num1->num[i] = 0; 64 num1->digit = k; //转换后的数据位数 65 for (i = 0, k--; k >= 0; k--, i++) //将临时数组各位反置保存到数组num中 66 num1->num[i] = temp[k]; 67 BigIntTrim(num1); //整理输入的大整数 68 } 69 void BigIntPrint(pBIGINT result) //输出大整数 70 { 71 int j; 72 if (result->minus == -1) //是负数 73 printf("-"); //输出负数 74 if (result->digit == 1 && result->num[0] == 0) //若大整数为0 75 printf("0"); 76 else //不为0 77 { 78 for (j = result->digit - 1; j >= 0; j--) //从高位到低位输出 79 printf("%d", result->num[j]); 80 } 81 } 82 int BigIntEqual(pBIGINT num1, pBIGINT num2) //比较绝对值大小 83 { 84 int i; 85 if (num1->digit > num2->digit) //num1的位数大于num2 86 return 1; 87 else if (num1->digit < num2->digit) //num1的位数小于num2 88 return -1; 89 else //两数位数相等 90 { 91 i = num1->digit - 1; //num1的数据位数 92 while (i >= 0) //从高位向低位比 93 { 94 if (num1->num[i] > num2->num[i]) //num1对应位大于num2 95 return 1; 96 else if (num1->num[i] < num2->num[i]) //num1对应位小于num2 97 return -1; 98 else 99 i--; //比较下一位 100 } 101 } 102 return 0; //相等 103 } 104 void BigIntAdd(pBIGINT num1, pBIGINT num2, pBIGINT result) 105 { 106 int i; 107 i = BigIntEqual(num1, num2); //比较两数绝对值大小 108 if (i < 0) //num1绝对值小于num2 109 { 110 pBIGINT temp; 111 temp = num1; //交换两数 112 num1 = num2; 113 num2 = temp; 114 } 115 if (num1->minus * num2->minus < 0) //符号不同,则执减法 116 { 117 if (i == 0) //两数相等 118 { 119 result->digit = 1; //结果长度为一位数,就是数值0 120 result->num[0] = 0; //结果值为0 121 result->minus = 1; //结果设为正号 122 return; //返回 123 } 124 BigIntSub1(num1, num2, result); //调用相减函数完成异号相加的情况 125 } else 126 BigIntAdd1(num1, num2, result); //调用相加函数完成同号相加 127 } 128 void BigIntAdd1(pBIGINT num1, pBIGINT num2, pBIGINT result) 129 { 130 int i, carry; 131 carry = 0; 132 result->minus = num1->minus; //保存符号 133 for (i = 0; i < num1->digit; i++) //将被加数复制到结果数组中 134 result->num[i] = num1->num[i]; 135 for (i = 0; i < num2->digit; i++) //num2中的数小,可能位数也小些 136 { 137 result->num[i] = result->num[i] + num2->num[i] + carry; //将对应位的数和进位数相加 138 carry = result->num[i] / 10; //计算进位数据 139 result->num[i] = result->num[i] % 10; //保留一位 140 } 141 if (carry) //若最后还有进位 142 result->num[i] = result->num[i] + carry; 143 BigIntTrim(result); //整理结果 144 } 145 void BigIntSub1(pBIGINT num1, pBIGINT num2, pBIGINT result) //异号相减函数 146 { 147 int i, borrow; 148 result->minus = num1->minus; //因num1绝对值比num2大,结果符号与num1相同 149 borrow = 0; 150 for (i = 0; i < num1->digit; i++) //将被减数的内容复制到结果中 151 result->num[i] = num1->num[i]; 152 for (i = 0; i <= num2->digit; i++) 153 { 154 result->num[i] = result->num[i] - num2->num[i] - borrow; //num1减去num2,并减去低位的借位 155 if (result->num[i] < 0) //若为负数 156 { 157 result->num[i] = 10 + result->num[i]; //向高位借位 158 borrow = 1; //设置借位值 159 } else 160 borrow = 0; 161 } 162 if (borrow == 1) 163 result->num[i] = result->num[i] - borrow; 164 BigIntTrim(result); 165 /*i = num1->digit; 166 while (i > 0) 167 { 168 if (result->num[i] == 0) 169 i--; 170 else 171 break; 172 } 173 result->digit = i; //保存结果位数*/ 174 } 175 void BigIntSub(pBIGINT num1, pBIGINT num2, pBIGINT result) //减法函数 176 { 177 num2->minus = -1 * num2->minus; //将减数的符号取反 178 BigIntAdd(num1, num2, result); //调用加法函数 179 } 180 void BigIntMul(pBIGINT num1, pBIGINT num2, pBIGINT result) 181 { 182 char carry, temp; 183 int i, j, pos; 184 for (i = 0; i < num1->digit + num2->digit; i++) //结果数组和中间数组清0 185 result->num[i] = 0; 186 for (i = 0; i < num2->digit; i++) //用乘数的每1位乘以被乘数 187 { 188 carry = 0; //清除进位 189 for (j = 0; j < num1->digit; j++) //被乘数的每1位 190 { 191 temp = num2->num[i] * num1->num[j] + carry; //相乘并加上进位 192 carry = temp / 10; //计算进位carry 193 temp = temp % 10; //计算当前位的值 194 pos = i + j; 195 result->num[pos] += temp; //计算结果累加到临时数组中 196 carry = carry + result->num[pos] / 10; //计算进位 197 result->num[pos] = result->num[pos] % 10; 198 } 199 if (carry > 0) 200 { 201 result->num[i + j] = carry; //加上最高位进位 202 result->digit = i + j + 1; //保存结果位数 203 } else 204 result->digit = i + j; //保存结果位数 205 } 206 result->minus = num1->minus * num2->minus; //结果的符号 207 } 208 void BigIntDiv(pBIGINT num1, pBIGINT num2, pBIGINT result, pBIGINT residue) //除法函数函数 》?跞サ臀坏慕栉?雗um1相同 数 209 { 210 BIGINT quo1, residuo1, quo2; 211 int i, j, k, m; //k保存试商结果,m保存商的位数 212 char t; 213 result->minus = num1->minus * num2->minus; //商的符号 214 residue->num = (char *) malloc(sizeof(char) * num2->digit); //分配余数的内存空间 215 residue->digit = num2->digit+1; //设置余数的初始位数与除数相同 216 for (i = 0; i < residue->digit; i++) //将余数全部清0 217 residue->num[i] = 0; 218 m = 0; 219 for (i = num1->digit - 1; i >= 0; i--) 220 { 221 residue->digit=num2->digit+1; //重新设置余数的位数比除数多一位 222 for (j = residue->digit - 1; j > 0; j--) //移余数 223 residue->num[j] = residue->num[j - 1]; //将序号低位的数据移向高位(实际是将余数中的最高位去除) 224 residue->num[0] = num1->num[i]; //复制被除数中的一位到余数的最低位中 225 BigIntTrim(residue);//整理余数 226 k = 0; //试商 227 while (BigIntEqual(residue, num2) >= 0) //比较余数与除数的大小 228 { 229 BigIntSub1(residue, num2, residue); //用余数减去除数,差值保存在余数中 230 k++; //试商加1 231 } 232 result->num[m++] = k; //保存商 233 } 234 result->digit = m; //保存商的位数 235 for (i = 0; i < m / 2; i++) //将商各位反转(在计算过程中序号0保存的是商的高位) 236 { 237 t = result->num[i]; 238 result->num[i] = result->num[m - 1 - i]; 239 result->num[m - 1 - i] = t; 240 } 241 BigIntTrim(result); //整理商 242 BigIntTrim(residue); //整理余数 243 } 244 int main() 245 { 246 BIGINT num1, num2, result, residue; //参与运算的数、结果、余数 247 int i = 0, len; 248 char op; 249 printf("输入最大数的位数:"); 250 scanf("%d", &len); 251 if (!(num1.num = (char *) malloc(sizeof(char) * (len + 1)))) 252 { 253 printf("内存分配失败!\n"); 254 exit(0); 255 } 256 num1.digit = len + 1; 257 if (!(num2.num = (char *) malloc(sizeof(char) * (len + 1)))) 258 { 259 printf("内存分配失败!\n"); 260 exit(0); 261 } 262 num2.digit = len + 1; 263 if (!(result.num = (char *) malloc(sizeof(char) * (2 * len + 1)))) 264 { 265 printf("内存分配失败!\n"); 266 exit(0); 267 } 268 result.digit = 2 * len + 1; 269 for (i = 0; i < result.digit; i++) //清空结果集 270 result.num[i] = 0; 271 printf("选择大整数的运算(+、-、*、/):"); 272 fflush(stdin); 273 scanf("%c", &op); 274 switch (op) 275 { 276 case ‘+‘: 277 printf("\n输入被加数:"); 278 scanf("%s", num1.num); 279 printf("\n输入加数:"); 280 scanf("%s", num2.num); 281 BigIntTrans(&num1); 282 BigIntTrans(&num2); 283 BigIntAdd(&num1, &num2, &result); //加法 284 break; 285 case ‘-‘: 286 printf("\n输入被减数:"); 287 scanf("%s", num1.num); 288 printf("\n输入减数:"); 289 scanf("%s", num2.num); 290 BigIntTrans(&num1); 291 BigIntTrans(&num2); 292 BigIntSub(&num1, &num2, &result); //减法 293 break; 294 case ‘*‘: 295 printf("\n输入被乘数:"); 296 scanf("%s", num1.num); 297 printf("\n输入乘数:"); 298 scanf("%s", num2.num); 299 BigIntTrans(&num1); 300 BigIntTrans(&num2); 301 BigIntMul(&num1, &num2, &result); //乘法 302 break; 303 case ‘/‘: 304 printf("\n输入被除数:"); 305 scanf("%s", num1.num); 306 printf("\n输入除数:"); 307 scanf("%s", num2.num); 308 BigIntTrans(&num1); 309 BigIntTrans(&num2); 310 if (num2.digit == 1 && num2.num[0] == 0) //大整数为0 311 printf("除数不能为0!\n"); 312 else 313 BigIntDiv(&num1, &num2, &result, &residue); //除法法 314 break; 315 } 316 if (op == ‘/‘) 317 { 318 if (!(num2.digit == 1 && num2.num[0] == 0)) //为除法且除数不为0 319 { 320 printf("商:"); 321 BigIntPrint(&result); 322 printf("\t余数:"); 323 BigIntPrint(&residue); 324 } 325 } else 326 { 327 printf("\n结果:"); 328 BigIntPrint(&result); 329 } 330 331 getch(); 332 return 0; 333 }
时间: 2024-10-10 06:41:30