前几天写的高精度的基本运算,包括整数和浮点数加减乘除,乘方和整数的阶乘.乘法和除法,以及乘方和阶乘都是以加法为基础,调用了加法的函数.写得很简陋,但是功能还可以,希望各位网友试用,如找到BUG请留言,谢谢!/*用数组存储数字,可以超越数据类型的限制,实现超长整型,高精度基本运算 */ #include<stdio.h>#include<stdlib.h>#include<string.h>#define MAX 200 int Compare(const char *a, const char *b);void IntAddition(char *augend, char *addend, char *sum);void IntSubtration(char *minuend, char *subtrahend, char *difference);void IntMultiplication(char *multiplicand, char *multiplier, char *product);void IntDivision(char *dividend, char *divisor, char *quotient, char *remainder);int Radix(char *toStr, char *fromStr);void FloatAddition(char *augend, char *addend, char *sum);void FloatSubtration(char *minuend, char *subtrahend, char *difference);void FloatMultiplication(char *multiplicand, char *multiplier, char *product);void FloatDivision(char *dividend, char *divisor, char *quotient, int precision);void Insert(char s[], int left, int right);int IsCycle(char a[][MAX], int label);void Factorial(char *base, char *result); void IntPower(char *base, char *exponential, char *power);void FloatPower(char *base, char *exponential, char *power); int main(void){ char a[MAX] = {0}; char b[MAX] = {0}; char c[3*MAX] = {0}; char d[MAX] = {0}; puts("请输入第一个数:"); gets(a); puts("请输入第二个数:"); gets(b); IntAddition(a, b, c); puts("两者之和:"); puts(c); IntSubtration(a, b, c); puts("两者之差:"); puts(c); IntMultiplication(a, b, c); puts("两者之积:"); puts(c); IntDivision(a, b, c, d); puts("两者之商:"); puts(c); puts("余数:"); puts(d); FloatAddition(a, b, c); puts("两者之和:"); puts(c); FloatSubtration(a, b, c); puts("两者之差:"); puts(c); FloatMultiplication(a, b, c); puts("两者之积:"); puts(c); FloatDivision(a, b, c, MAX); puts("两者之商:"); puts(c); IntPower(a, b, c); puts("两者之乘方:"); puts(c); FloatPower(a, b, c); puts("两者之乘方:"); puts(c); Factorial(a, c); puts("a的阶乘:"); puts(c); system("pause"); return 0; } /*函数功能:利用字符串实现超长整型,高精度加法运算 输入变量:char *augend,存储了被加数的字符串 char *addend,存储了加数的字符串 char *sum,用来存储两数之和的字符串 输出变量:char *sum,用来存储两数之和的字符串 返回值: 无 */void IntAddition(char *augend, char *addend, char *sum){ int cAug[MAX] = {0};//用来存储被加数的整型数组 int cAdd[MAX] = {0};//用来存储加数的整型数组 int cSum[MAX] = {0};//用来存储两数之和的整型数组 int lenAug = strlen(augend), lenAdd = strlen(addend);//被加数和加数字符串的长度 int lenMin = lenAug < lenAdd ? lenAug : lenAdd;//两个加数的长度中的较小值 int i; //逆序复制加数和被加数到整型数组(因为加法运算是从低位开始) for (i=0; i<lenAug; i++) cAug[i] = augend[lenAug-1-i] - '0'; for (i=0; i<lenAdd; i++) cAdd[i] = addend[lenAdd-1-i] - '0'; int carry = 0;//进位 int s = 0; //两数之和 for (i=0; i<lenMin; i++)//加法运算过程 { s = cAug[i] + cAdd[i] + carry;//两个加数和进位之和作为当前位的和 cSum[i] = s % 10;//存储当前位 carry = s / 10;//获取进位 } //处理加数或被加数超出长度lenMin的部分 while (i < lenAug) { s = cAug[i] + carry; cSum[i] = s % 10; carry = s / 10; i++; } while (i < lenAdd) { s = cAdd[i] + carry; cSum[i] = s % 10; carry = s / 10; i++; } if (carry > 0)//处理最后一个进位 cSum[i++] = carry; int j; for (j=0; j<i; j++)//逆序存储两数之和到字符串sum sum[j] = cSum[i-1-j] + '0'; sum[i] = '\0';} //比较两个用字符串存储的超长正整数的大小,若a>b,返回1;a==b,返回0;a<b,返回-1 int Compare(const char *a, const char *b){ int lenA = strlen(a); int lenB = strlen(b); if (lenA != lenB) return lenA > lenB ? 1 : -1; else return strcmp(a, b);} /*函数功能:利用字符串实现超长整型,高精度减法运算 输入变量:char *minuend,存储了被减数的字符串 char *subtrahend,存储了减数的字符串 char *difference,用来存储两数之差的字符串 输出变量:char *difference,用来存储两数之差的字符串 返回值: 无 */void IntSubtration(char *minuend, char *subtrahend, char *difference){ if (strcmp(minuend, subtrahend) == 0)//如果两数相等,返回"0" { strcpy(difference, "0"); return; } int cM[MAX] = {0};//用来存储被减数的整型数组 int cS[MAX] = {0};//用来存储减数的整型数组 int cD[MAX] = {0};//用来存储两数之差的整型数组 int lenM = strlen(minuend), lenS = strlen(subtrahend);//被减数和减数字符串的长度 int lenMin = lenM < lenS ? lenM : lenS;//两个减数的长度中的较小值 int flag;//记录结果是整数还是负数 int i; //逆序复制减数和被减数到整型数组(因为减法运算是从低位开始),保证cM大于cS if (Compare(minuend, subtrahend) > 0) { flag = 0;//被减数大于减数,结果为正数 for (i=0; i<lenM; i++) cM[i] = minuend[lenM-1-i] - '0'; for (i=0; i<lenS; i++) cS[i] = subtrahend[lenS-1-i] - '0'; } else { flag = 1;//被减数小于减数,结果为负数,此时要用subtrahend - minuend for (i=0; i<lenM; i++) cS[i] = minuend[lenM-1-i] - '0'; for (i=0; i<lenS; i++) cM[i] = subtrahend[lenS-1-i] - '0'; } for (i=0; i<lenMin; i++)//减法运算过程 { if (cM[i] >= cS[i])//被减数大于减数,直接相减 cD[i] = cM[i] - cS[i]; else //否则要向前借位 { cD[i] = cM[i] + 10 - cS[i]; --cM[i+1]; } } //处理减数或被减数超出长度lenMin的部分 int len = lenM > lenS ? lenM : lenS; while (i < len) { if (cM[i] >= 0) cD[i] = cM[i]; else { cD[i] = cM[i] + 10; --cM[i+1]; } i++; } while (cD[i-1] == 0) i--; int j = 0; if (flag == 1)//如果被减数小于减数,返回一个负数 difference[j++] = '-'; int k; for (k=i-1; k>=0; k--,j++)//逆序存储两数之差到字符串sum difference[j] = cD[k] + '0'; difference[j] = '\0';} /*函数功能:利用字符串实现超长整型,高精度乘法运算 输入变量:char *minuend,存储了被乘数的字符串 char *subtrahend,存储了乘数的字符串 char *difference,用来存储两数之乘积的字符串 输出变量:char *difference,用来存储两数之乘积的字符串 返回值: 无 */void IntMultiplication(char *multiplicand, char *multiplier, char *product){ int cD[MAX] = {0};//用来存储被乘数的整型数组 int cR[MAX] = {0};//用来存储乘数的整型数组 int cP[MAX] = {0};//用来存储两数之乘积的整型数组 char tcP[MAX] = "";//用来存储两数之乘积的整型数组 int lenD = strlen(multiplicand), lenR = strlen(multiplier);//被乘数和乘数字符串的长度 int i, j, k; //逆序复制乘数和被乘数到整型数组(因为乘法运算是从低位开始) for (i=0; i<lenD; i++) cD[i] = multiplicand[lenD-1-i] - '0'; for (i=0; i<lenR; i++) cR[i] = multiplier[lenR-1-i] - '0'; int carry;//进位 int mul = 0; //两数之乘积 strcpy(product, "0"); //先使product的值为0 for (i=0; i<lenR; i++)//乘法运算过程 { carry = 0;//进位 for (j=0; j<lenD; j++)//乘数的每一位都和被乘数进行乘法运算 { mul = cD[j] * cR[i] + carry;//两个乘数之积与进位相加作为当前位乘积 cP[j] = mul % 10;//存储当前位 carry = mul / 10;//获取进位 } if (carry > 0)//获取最后一个进位 cP[j++] = carry; while (cP[j-1] == 0)//去掉多余的0 --j; //逆序复制当前位的乘积tP到字符串tcP for (k=0; k<j; k++) tcP[k] = cP[j-1-k] + '0'; for (j=0; j<i; j++)//注意各位数得到的结果应相应左移 tcP[k++] = '0'; tcP[k] = '\0'; IntAddition(product, tcP, product);//对字符串进行加法运算 } } /*函数功能:利用字符串实现超长整型,高精度除法运算 输入变量:char *dividend,存储了被除数的字符串 char *divisor,存储了除数的字符串 char *quotient,用来存储两数相除之商的字符串 char *remainder,用来存储两数相除之余数的字符串 输出变量:char *quotient,用来存储两数相除之商的字符串 char *remainder,用来存储两数相除之余数的字符串返回值: 无 */void IntDivision(char *dividend, char *divisor, char *quotient, char *remainder){ if (Compare(dividend, divisor) == 0)//被除数等于除数 { strcpy(quotient, "1"); strcpy(remainder, "0"); return ; } if (strcmp(divisor, "0") == 0 || Compare(dividend, divisor) < 0)//被除数小于除数 { strcpy(quotient, "0"); strcpy(remainder, dividend); return ; } char buf[2] = "0";//临时数组依次存储被除数的每一位数 int i, s, k; strcpy(remainder, ""); //先使product的值为空 for (i=0,k=0; dividend[i]!='\0'; i++) { s = 0; buf[0] = dividend[i]; strcat(remainder, buf);//接上被除数的一位数,改变当前余数 while (Compare(remainder, divisor) >= 0)//连减试商 { s++; IntSubtration(remainder, divisor, remainder); } quotient[k++] = s + '0';//记录每一位得到的商值 if (strcmp(remainder, "0") == 0) strcpy(remainder, ""); //使product的值为空,去掉多余的0 } quotient[k] = '\0'; //去掉多余的0 int j; for (i=0; quotient[i]=='0'; i++) ; for (j=i; j<=k; j++) quotient[j-i] = quotient[j]; } /*函数功能:去掉原字符串的小数点,把浮点数转化成整数后存储到新的字符串 输入变量:char *toStr,存储了转化后的整数的字符串 char *fromStr,存储了原浮点数的字符串输出变量:char *toStr,存储了转化后的整数的字符串返回值: 原浮点数小数部分的长度 */int Radix(char *toStr, char *fromStr) { int i = 0, j = 0; int len; while (fromStr[i] != '.' && fromStr[i] != '\0') { toStr[j++] = fromStr[i++]; } len = i++;//跳过小数点,并记录该位置 while (fromStr[i] != '\0') { toStr[j++] = fromStr[i++]; } return i - len - 1;//记录小数点后的数字个数 } /*函数功能:利用字符串实现超长浮点型,高精度加法运算 输入变量:char *augend,存储了被加数的字符串 char *addend,存储了加数的字符串 char *sum,用来存储两数之和的字符串 输出变量:char *sum,用来存储两数之和的字符串 返回值: 无 */void FloatAddition(char *augend, char *addend, char *sum){ char cAug[MAX] = {0};//用来存储被加数的字符串 char cAdd[MAX] = {0};//用来存储加数的字符串 char cSum[MAX] = {0};//用来存储两数之和的字符串 int lenAug, lenAdd, lenSum;//分别存储三个数的小数点后的数字个数 int i, topAug, topAdd; //去掉小数点,把浮点数转化成整数后存储到新的字符串 lenAug = Radix(cAug, augend); lenAdd = Radix(cAdd, addend); topAug = strlen(cAug); topAdd = strlen(cAdd); //在小数部分较短的字符串后补零,使得两个数的小数部分长度相等 if (lenAug > lenAdd) { lenSum = lenAug; for (i=lenAug-lenAdd; i>0; i--) cAdd[topAdd++] = '0'; } else { lenSum = lenAdd; for (i=lenAdd-lenAug; i>0; i--) cAug[topAug++] = '0'; } cAdd[topAdd++] = '\0'; cAug[topAug++] = '\0'; //执行整数加法运算 IntAddition(cAdd, cAug, cSum); i = strlen(cSum) - 1; while (lenSum > 0 && cSum[i] == '0')//去掉小数部分多余的零 { i--; lenSum--; } cSum[i+2] = '\0'; while (lenSum > 0)//在适当位置插入'.’ { cSum[i+1] = cSum[i]; i--; lenSum--; } cSum[i+1] = '.'; strcpy(sum, cSum);} /*函数功能:利用字符串实现超长浮点型,高精度减法运算 输入变量:char *minuend,存储了被减数的字符串 char *subtrahend,存储了减数的字符串 char *difference,用来存储两数之差的字符串 输出变量:char *difference,用来存储两数之差的字符串 返回值: 无 */void FloatSubtration(char *minuend, char *subtrahend, char *difference){ if (strcmp(minuend, subtrahend) == 0)//如果两数相等,返回"0" { strcpy(difference, "0"); return; } char cM[MAX] = {0};//用来存储被减数的字符串 char cS[MAX] = {0};//用来存储减数的字符串 char cD[MAX] = {0};//用来存储两数之差的字符串 int lenM, lenS, lenD;//分别存储三个数的小数点后的数字个数 int i, topM, topS; //去掉小数点,把浮点数转化成整数后存储到新的字符串 lenM = Radix(cM, minuend); lenS = Radix(cS, subtrahend); topM = strlen(cM); topS = strlen(cS); //在小数部分较短的字符串后补零,使得两个数的小数部分长度相等 if (lenM > lenS) { lenD = lenM; for (i=lenM-lenS; i>0; i--) cS[topS++] = '0'; } else { lenD = lenS; for (i=lenS-lenM; i>0; i--) cM[topM++] = '0'; } cM[topM++] = '\0'; cS[topS++] = '\0'; //执行整数减法运算 IntSubtration(cM, cS, cD); i = strlen(cD) - 1; while (lenD > 0 && cD[i] == '0')//去掉小数部分多余的零 { i--; lenD--; } cD[i+2] = '\0'; while (lenD > 0)//在适当位置插入'.’ { cD[i+1] = cD[i]; i--; lenD--; } cD[i+1] = '.'; if (i == -1)//结果为0的情况 { cD[0] = '0'; cD[1] = '.'; cD[2] = '\0'; } strcpy(difference, cD);} /*函数功能:利用字符串实现超长浮点型,高精度乘法运算 输入变量:char *minuend,存储了被乘数的字符串 char *subtrahend,存储了乘数的字符串 char *difference,用来存储两数之乘积的字符串 输出变量:char *difference,用来存储两数之乘积的字符串 返回值: 无 */void FloatMultiplication(char *multiplicand, char *multiplier, char *product){ char cD[MAX] = {0};//用来存储被乘数的字符串 char cR[MAX] = {0};//用来存储乘数的字符串 char cP[2*MAX] = {0};//用来存储两数之乘积的字符串 int lenD, lenR, lenP;//分别存储三个数的小数点后的数字个数 //去掉小数点,把浮点数转化成整数后存储到新的字符串 lenD = Radix(cD, multiplicand); lenR = Radix(cR, multiplier); lenP = lenD + lenR; IntMultiplication(cD, cR, cP); int i = strlen(cP) - 1; while (lenP > 0 && cP[i] == '0')//去掉小数部分多余的零 { i--; lenP--; } cP[i+2] = '\0'; while (lenP > 0 && i >= 0)//在适当位置插入'.’ { cP[i+1] = cP[i]; i--; lenP--; } cP[i+1] = '.'; if (i == -1)//如果小数点在第一位,在前面添0 { for (i=strlen(cP); i>0; --i) cP[i+1+lenP] = cP[i]; for (i=0; i<lenP; ++i) cP[i+2] = '0'; cP[1] = '.'; cP[0] = '0'; } strcpy(product, cP);} /*函数功能:利用字符串实现超长浮点型,高精度除法运算 输入变量:char *dividend,存储了被除数的字符串 char *divisor,存储了除数的字符串 char *quotient,用来存储两数相除之商的字符串 int precision,用来存储小数部分的精度 输出变量:char *quotient,用来存储两数相除之商的字符串 返回值: 无 */void FloatDivision(char *dividend, char *divisor, char *quotient, int precision){ if (Compare(dividend, divisor) == 0)//被除数等于除数 { strcpy(quotient, "1."); return ; } if (strcmp(divisor, "0.")==0 || strcmp(divisor, "0")==0)//被除数小于除数 { strcpy(quotient, "0."); return ; } char cD[MAX] = {0};//用来存储被除数的字符串 char cR[MAX] = {0};//用来存储除数的字符串 char cQ[MAX] = {0};//用来存储两数之商的字符串 char cY[MAX] = {0};//用来存储两数之当前余数的字符串 char tcY[MAX][MAX] = {0};//用来存储两数之所有余数的字符串 int lenD, lenR, lenQ;//分别存储三个数的小数点后的数字个数 int i, j, t, s, left; //去掉小数点,把浮点数转化成整数后存储到新的字符串 lenD = Radix(cD, dividend); lenR = Radix(cR, divisor); //如果被除数的小数部分长,则求出多出的小数长度,以便插入小数点,否则补0 if (lenD > lenR) lenQ = lenD - lenR; else { lenQ = 0; i = strlen(cD); for (j=0; j<lenR-lenD; j++) cD[i++] = '0'; cD[i] = '\0'; } IntDivision(cD, cR, cQ, cY);//得到整数部分的商 t = j = strlen(cQ); //插入小数点 for (i=0; i<lenQ; ++i,--t) { if (t > 0) cQ[t] = cQ[t-1]; else { t = 1; cQ[t] = '0'; } } cQ[t] = '.'; if (t == 0)//如果小数点在第一位,在前面添0 { for (i=j++; i>=0; --i) cQ[i+1] = cQ[i]; cQ[0] = '0'; } ++j; //处理小数部分 i = t = 0; while (i < precision && strcmp(cY, "0")!=0) { strcpy(tcY[t++], cY);//存储所有的余数(小数部分) left = IsCycle(tcY, t-1);//判断是否出现循环节 if (left != t-1) //如果找到相等的余数,就结束循环 { Insert(cQ, j-(t-1-left), j);//在字符数组s中适当位置插入符号'(' if (cQ[j-1] == '(' && cQ[j] == '0')//去除多余的循环节,即特殊处理可以除尽的情况 cQ[--j] = '\0'; else//否则用“()”把循环节括起来 { cQ[j+1] = ')'; cQ[j+2] = '\0'; } break; } //否则继续计算小数部分 strcat(cY, "0"); s = 0; if (Compare(cY, cR) < 0) cQ[j++] = '0'; else { while (Compare(cY, cR) >= 0) { ++s; IntSubtration(cY, cR, cY); } cQ[j++] = s + '0'; } ++i; } if (i == precision) cQ[j] = '\0'; strcpy(quotient, cQ);} /*函数介绍:在字符数组s中适当位置插入符号'(' char s[]: 字符数组,用来存储给定分数的小数形式 int left:数组a中需要插入符号'('的位置 int right:数组a中当前最右边的数字之后的下标 */ void Insert(char s[], int left, int right){ int i; for (i=right; i>left; i--) //把数组元素后移,为插入符号'('腾出位置 { s[i] = s[i-1]; } s[left] = '(';//插入符号'('} /*函数介绍:判断当前余数是否与前面的某个余数相同,若相同,返回该余数的位置下标 char a[][MAX]: 字符数组,存储了当前余数 int label:当前余数的下标*/ int IsCycle(char a[][MAX], int label) { int i; for (i=0; i<label; i++) { if (strcmp(a[i], a[label]) == 0) //如果数组中有与当前余数相同的余数,返回该余数的位置下标 return i; } return label; //否则返回当前余数的位置下标 } /*函数功能:利用字符串实现超长整型,高精度乘方运算 输入变量:char *base,存储了底数的字符串 char *exponential,存储了指数的字符串 char *power,用来存储两数相除之乘方的字符串 输出变量:char *power,用来存储两数相除之乘方的字符串返回值: 无 */void IntPower(char *base, char *exponential, char *power){ if (strcmp(exponential, "0") == 0)//如果指数为0,返回1 { strcpy(power, "1"); return ; } if (strcmp(exponential, "1") == 0)//如果指数为1,返回底数 { strcpy(power, base); return ; } char cRem[MAX] = {0};//用来存储余数的整型数组 char cExp[MAX] = {0};//用来存储指数的整型数组 char cPow[4*MAX] = {0};//用来存储两数之乘方的整型数组 IntDivision(exponential, "2", cExp, cRem);//将指数整除2 IntPower(base, cExp, cPow);//递归计算乘方,注意此时指数为原来的一半 IntMultiplication(cPow, cPow, power);//将递归得到的乘方结果相乘 if (strcmp(cRem, "1") == 0)//如果指数是奇数,乘方结果再乘以底数 IntMultiplication(power, base, power); } /*函数功能:利用字符串实现超长浮点型,高精度乘方运算,注意指数为整数 输入变量:char *base,存储了底数的字符串 char *exponential,存储了指数的字符串 char *power,用来存储两数相除之乘方的字符串 输出变量:char *power,用来存储两数相除之乘方的字符串返回值: 无 */void FloatPower(char *base, char *exponential, char *power){ if (strcmp(exponential, "0") == 0)//如果指数为0,返回1 { strcpy(power, "1"); return ; } if (strcmp(exponential, "1") == 0)//如果指数为1,返回底数 { strcpy(power, base); return ; } char cRem[MAX] = {0};//用来存储余数的整型数组 char cExp[MAX] = {0};//用来存储指数的整型数组 char cPow[4*MAX] = {0};//用来存储两数之乘方的整型数组 IntDivision(exponential, "2", cExp, cRem);//将指数整除2 FloatPower(base, cExp, cPow);//递归计算乘方,注意此时指数为原来的一半 FloatMultiplication(cPow, cPow, power);//将递归得到的乘方结果相乘 if (strcmp(cRem, "1") == 0)//如果指数是奇数,乘方结果再乘以底数 FloatMultiplication(power, base, power); } /*函数功能:利用字符串实现超长整型,高精度除法阶乘运算 输入变量:char *base,存储了被求阶乘的数的字符串 char *result,存储了阶乘结果的字符串输出变量:char *result,存储了阶乘结果的字符串返回值: 无 */void Factorial(char *base, char *result){ char cBase[MAX] = {0};//用来存储被求阶乘的数的整型数组 strcpy(cBase, base); strcpy(result, "1"); while (strcmp(cBase, "1") > 0) { IntMultiplication(cBase, result, result);//按照阶乘的定义计算 IntSubtration(cBase, "1", cBase); }}

评论