日历

2008 7.5 Sat
  12345
6789101112
13141516171819
20212223242526
2728293031  
«» 2008 - 7 «»

文章搜索

日志文章

2008年03月15日 22:41:36

c语言实现大数相加,大数相乘

最近在公司闲得无聊,正好一朋友叫我帮他写个大数相加,大数相乘函数,说是某公司程序员初试题,个人对C熟悉点,所以用C写这两个函数,考虑过许多算法,如算大数相加可把大数拆成若干个整型数用链表连起来,然后从后向前相加进位,但我感觉这样运算效率并不会提高多少,相反写起程序来更麻烦,所以我用人们笔算的方法写.
大数相加就是从个位开始一位位往前加.
大数相乘就是把其中一个大数一位位和另一个数相乘累加.
就是我们在草稿纸上笔算的方法了,注释我写的很多了,具体实现处法请看下面代码.

#include "stdio.h"
#include "string.h"
#include "stdlib.h"

/*判断字符串是否全是数字(返回是否合法)*/
char IsLegalData(char *strData)
{
   int i;
   int lenData;
   char ret = 1;    /*默认参数合法*/
   
   lenData = strlen(strData);
   if ( lenData < 1 )
   {
       ret = 0;    /*空字符串*/
   }

   if ( ret == 1 )
   {
       for (i=0; i<lenData-2; i++)
       {
           if ( (strData < 0x30) || (strData > 0x39) )
           {
               ret = 0;    /*字符串中有的不是数字,不合法*/
               break;
           }
       }
   }

   return ret;
}

/*给字符数组赋值*/
void SetChaArr(char *arr, char x, int lenArr)
{
   int i;
   
   for (i=0; i<lenArr; i++)
   {
       arr = x;
   }
}

/*去掉字符串大数前面的0*/
void RemovePreZero(char *strData)
{
   int i, j;
   int lenData;

   lenData = strlen(strData);    /*长度*/
   j = 0;
   for (i=0; i<lenData; i++)
   {
       if ( strData == 0x30 )
       {
           j += 1;    /*累计0的个数*/
       }
       else
       {
           break;    /*非零则跳出*/
       }
   }
   
   /*向前移位*/
   if ( j == lenData )
   {
       /*全0,则只给一个0*/
       strData[0] = 0x30;
       strData[1] = '\0';
   }
   else
   {
       if ( j > 0 )
       {
           /*前面有0移位*/
           for (i=0; i<lenData-j; i++)
           {
               strData = strData[i+j];
           }
           strData = '\0';
       }
   }
}

/*两个字符数字相加(返回是否进位)*/
int AddBigDataSub(char cx, char cy, int isCarry, char *sum)
{
   int ret = 0;

   *sum = cx + cy + isCarry - 0x30;    /*相加*/
   if ( *sum > 0x39 )
   {
       *sum -= 10;        /*大于9则进位减10*/
       ret = 1;        /*有进位*/
   }

   return ret;
}

/*从字符串中取字符*/
char GetChaFromStr(char *strData, int index)
{
   char ret;

   if ( index < 0 )
   {
       ret = 0x30;
   }
   else
   {
       ret = strData[index];
   }

   return ret;
}

/*两大数相加函数*/
char* AddBigData(char *strA, char *strB)
{
   int lenA, lenB, lenMax;
   int i, j, k;
   char legalFlag = 0;        /*默认参数不合法*/
   char *ret = NULL;

   /*参数合法性判断*/
   if ( IsLegalData(strA) )
   {
       legalFlag = IsLegalData(strB);
   }

   if ( legalFlag )
   {
       /********参数合法*******/
       /*去掉大数前面多余的0,减少程序运算次数*/
       RemovePreZero(strA);
       RemovePreZero(strB);

       /*两字符串长度*/
       lenA = strlen(strA);
       lenB = strlen(strB);
       
       /*分配空间*/
       lenMax = (lenA>lenB)?(lenA + 2):(lenB + 2);
       ret = (char *)malloc(lenMax*sizeof(char));
       SetChaArr(ret, 0x30, lenMax);    /*全部给字符'0'*/
       ret[lenMax-1] = '\0';    /*最后一位给结束符*/
       
       /*从个位开始往高位相加*/
       k = lenMax - 2;
       lenA -= 1;
       lenB -= 1;
       i = (lenA>lenB)?lenA:lenB;
       j = 0;
       for (; i>=0; i--)
       {
           j = AddBigDataSub(GetChaFromStr(strA, lenA--), GetChaFromStr(strB, lenB--), j, &ret[k--]);
       }
       if ( j == 1 )
       {
           ret[k] += 1;    /*处理最高位相加后还进位*/
       }
       else
       {
           /*不进位则前移字符串*/
           for (i=0; i<lenMax-1; i++)
           {
               ret = ret[i+1];
           }
       }
   }
   else
   {
       /*参数不合法,返回空字符串*/
       ret = NULL;
   }

   return ret;
}

/*两个字符数字相乘*/
int MultiTwoCha(char cx, char cy, int carry, char *multi)
{
   int ret = 0;

   *multi = (cx - 0x30) * (cy - 0x30) + carry;    /*相乘结果*/
   if ( *multi > 9 )
   {
       ret = *multi / 10;    /*十位数为进位*/
       *multi = (*multi % 10) + 0x30;    /*个位数为此位结果*/
   }
   else
   {
       *multi += 0x30;
   }

   return ret;
}

/*大数相乘子过程(返回大数与另一个大数中一个字符相乘后生成的字符串)*/
/*index从乘数个位起到高位从0计数(如:个位=0,十位=1,百位=2....)*/
char *MultiBigDataSub(char *strData, char cy, int index)
{
   char *ret = NULL;
   int lenMax = 0;
   int i, j, k;

   /*依次相乘组合字符串*/
   if ( cy == 0x30 )
   {
       ret = NULL;        /*乘0返回空*/
   }
   else
   {
       /*相乘后最大长度*/
       i = strlen(strData);
       lenMax = i + 2 + index;

       /*分配空间*/
       ret = (char *)malloc(lenMax*sizeof(char));
       SetChaArr(ret, 0x30, lenMax);    /*全部给字符'0'*/
       ret[lenMax-1] = '\0';    /*最后一位给结束符*/

       /*依次相乘组合字符串*/
       j = 0;
       k = lenMax - 2 - index;
       for (i=i-1; i>=0; i--)
       {
           j = MultiTwoCha(strData, cy, j, &ret[k--]);
       }
       if ( j > 0 )
       {
           ret[k] = j + 0x30;    /*处理最前面字节相乘有进位*/
       }
       else
       {
           for (i=0; i<lenMax-1; i++)
           {
               ret = ret[i+1];
           }
       }
   }

   return ret;
}

/*两大数相乘函数*/
char* MultiBigData(char *strA, char *strB)
{
   int lenA, lenB, lenMax;
   int i, j, k;
   char legalFlag = 0;        /*默认参数不合法*/
   char *ret = NULL;
   char *strTmp = NULL;
   char init[] = "0";

   /*参数合法性判断*/
   if ( IsLegalData(strA) )
   {
       legalFlag = IsLegalData(strB);
   }

   if ( legalFlag )
   {
       /********参数合法*******/
       /*去掉大数前面多余的0,减少程序运算次数*/
       RemovePreZero(strA);
       RemovePreZero(strB);

       /*两字符串长度*/
       lenA = strlen(strA);
       lenB = strlen(strB);
       
       ret = init;
       if ( lenA > lenB )    /*减少运算次数,加个判断*/
       {
           for (i=lenB-1; i>=0; i--)
           {
               strTmp = MultiBigDataSub(strA, strB, lenB-1-i);
               if ( strTmp != NULL )
               {
                   ret = AddBigData(ret, strTmp);    /*每次累加*/
                   free(strTmp);    /*释放中间分配的空间*/
               }
           }
       }
       else
       {
           for (i=lenA-1; i>=0; i--)
           {
               strTmp = MultiBigDataSub(strB, strA, lenA-1-i);
               if ( strTmp != NULL)
               {
                   ret = AddBigData(ret, strTmp);
                   free(strTmp);
               }
           }
       }
   }
   else
   {
       /*参数不合法,返回空字符串*/
       printf("参数不合法!\n");
       ret = NULL;
   }

   return ret;
}


void main()
{
   char a[] = "4312505034431493253543514231423140903293414";
   char b[] = "3214321432535343124321423143243534534321441";
   char *sum = NULL;
   char *mul = NULL;

   sum = AddBigData(a, b);
   printf("\n************************************************\n");
   printf("%s\n\t+\n%s\n", a, b);
   printf("= %s\n", sum);
   printf("\n************************************************\n");
   free(sum);

   printf("\n\n");

   mul = MultiBigData(a, b);
   printf("\n************************************************\n");
   printf("%s\n\t*\n%s\n", a, b);
   printf("=%s\n", mul);
   printf("\n************************************************\n");
   free(mul);
}


我在vc6.0下调试成功,调试时间不长,如还存在BUG,请留言或通知本人
QQ: 136314890 MSN: sxwz2007@hotmail.com

类别: 无分类 |  评论(1) |  浏览(1241) |  收藏
一共有 1 条评论
1楼 心跳 2008年03月23日 11:14:17 Says:
呵呵,至少你这个乘法写出来啦,我现在还没有什么具体的思路呢。

跳是会跳的,看时间吧,再就是学习,其它学那么多的什么.net/dx什么的,那个只是别人公司开发出一种包啦,就像你自己写了个类,然后再封成包给别人用一样,别人也要学你的,最最基础的东西是每个人都要学的,所以要学基础的东西,再就是对编程有个全方位的了解,比如操作系统、数据结构、算法等等...

就你现在的水平来我这边找工作比我好找呵呵
发表评论