高精度计算2

高精度除法:

 

#include <stdio.h> #include <string.h> #define MAX_LEN 200 char szLine1[MAX_LEN + 10]; char szLine2[MAX_LEN + 10]; int an1[MAX_LEN + 10]; // 被除数,an1[0]对应于个位 int an2[MAX_LEN + 10]; // 除数,an2[0]对应于个位 int aResult[MAX_LEN + 10]; // 存放商,aResult[0]对应于个位 // 长度为pLen1的大整数p1送去长度为nLen2的大整数p2 int Substract(int *p1, int *p2, int nLen1, int nLen2) { int i; // 下面判断p1是否比p2大,如果不是,返回-1 if (nLen1 < nLen2) return -1; if (nLen1 == nLen2) for (i = nLen1 - 1; i >= 0; i--) if (p1[i] > p2[i]) break; else if (p1[i] < p2[i]) return -1; for (i = 0; i < nLen1; i++) { // 要求调用本函数确保当i>=nLen2时,p2[i]=0 p1[i] -= p2[i]; if (p1[i] < 0) { p1[i] += 10; p1[i + 1]--; } } for (i = nLen1 - 1; i >= 0; i--) if (p1[i]) // 找到最高位第一个不为0 return i + 1; return 0; // 全部为0,说明再会相等 } int main(void) { int t, n; scanf("%d", &n); for (t = 0; t < n; t++) { scanf("%s", szLine1); scanf("%s", szLine2); int i, j; int nLen1 = strlen(szLine1); memset(an1, 0, sizeof(an1)); memset(an2, 0, sizeof(an2)); memset(aResult, 0, sizeof(aResult)); for (j = 0, i = nLen1 - 1; i >= 0; i--) an1[j++] = szLine1[i] - '0'; int nLen2 = strlen(szLine2); for (j = 0, i = nLen2 - 1; i >= 0; i--) an2[j++] = szLine2[i] - '0'; if (nLen1 < nLen1) { printf("0/n"); continue; } int nTimes = nLen1 - nLen2; if (nTimes > 0) { for (i = nLen1 - 1; i >= nTimes; i--) an2[i] = an2[i - nTimes]; // 朝高位移动 for (; i >= 0; i--) // 低位补0 an2[i] = 0; nLen2 = nLen1; } for (j = 0; j <= nTimes; j++) { int nTmp; // 一直减不够为止 // 先减去若干个an2*(10的nTimes次方), // 不够叛乱了,再减去若干个an2*(10的nTimes-1次方),... while ((nTmp = Substract(an1, an2+j, nLen1, nLen2 - j)) >= 0) { nLen1 = nTmp; aResult[nTimes - j]++; // 每成功减一次,则将商的相应位加1 } } // 下面输出结果,先跳过高位0 for (i = MAX_LEN; i >= 0 && !aResult[i]; i--) ; if (i >= 0) for (; i >= 0; i--) printf("%d", aResult[i]); else printf("0"); putchar('/n'); } return 0; }

高精度乘法:

 #include <stdio.h> #include <string.h> #define MAX_LEN 200 int main(void) { int i, j, len1, len2; int a[MAX_LEN + 10], b[MAX_LEN + 10], c[MAX_LEN * 2 + 10]; char str1[MAX_LEN + 10], str2[MAX_LEN + 10]; // 初始化 for (i = 0; i < MAX_LEN + 10; i++) a[i] = b[i] = 0; for (i = 0; i < MAX_LEN * 2 + 10; i++) c[i] = 0; // 输入两个乘数 gets(str1); gets(str2); // 逆序将数存入整数数组 len1 = strlen(str1); for (j = 0, i = len1 - 1; i >= 0; i--) a[j++] = str1[i] - '0'; len2 = strlen(str2); for (j = 0, i = len2 - 1; i >= 0; i--) b[j++] = str2[i] - '0'; for (i = 0; i < len2; i++) // 第二个数乘以第一个数,每次一位 for (j = 0; j < len1; j++) c[i + j] = b[i] * a[j]; // 先乘起来,后面统一进位 for (i = 0; i < MAX_LEN * 2; i++) { if (c[i] >= 10) { c[i + 1] += c[i] / 10; c[i] %= 10; } } // 输出相乘结果 for (i = MAX_LEN * 2; !c[i] && i >= 0; i--) // 跨过高位0 ; if (i >= 0) for (; i >= 0; i--) printf("%d", c[i]); else printf("0"); return 0; }

 

麦森数的后五百位与总共位数

(不需判断是否是素数)

公式:2^p-1

#include <stdio.h> #include <memory.h> #include <math.h> #define LEN 125 // 每位元素存放4位,数组最多需要125个元素 // 计算高精度乘法a*b,结果的未500位放在a中 void Multiply(int *a, int *b) { int i, j; int nCarry; // 存进位 int nTmp; int c[LEN]; // 存放结果的末500位 memset(c, 0, sizeof(int) * LEN); for (i = 0; i < LEN; i++) { nCarry = 0; for (j = 0; j < LEN - i; j++) { nTmp = c[i + j] + a[j] * b[i] + nCarry; c[i + j] = nTmp % 10000; nCarry = nTmp / 10000; } } memcpy(a, c, LEN * sizeof(int)); } int main(void) { int i, p; int anPow[LEN]; // 存放不断增长的2的次幂 int aResult[LEN]; // 存放最终结果的末500位 scanf("%d", &p); printf("%d/n", (int)(p * log10(2.0)) + 1); // 下面将2的次幂初始化2^(2^0)(a^b表示a的b次方) // 最终结果初始化为1 anPow[0] = 2; aResult[0] = 1; for (i = 1; i < LEN; i++) { anPow[i] = 0; aResult[i] = 0; } while (p > 0) { // 下面计算2的P次方 // p=0则说明中的有效位都用过了,不需要再算下去if if (p & 1) // 判断此时p中最低位是否为1 Multiply(aResult, anPow); p >>= 1; Multiply(anPow, anPow); } aResult[0]--; // 2^p-1 // 输出结果 for (i = LEN - 1; i >= 0; i--) { if (i % 25 == 12) printf("%02d/n%02d", aResult[i] / 100, aResult[i] % 100); else { printf("%04d", aResult[i]); if (!(i % 25)) putchar('/n'); } } return 0; }

你可能感兴趣的:(c)