| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1144 人关注过本帖, 2 人收藏
标题:小鱼儿大数运算(前段时间写的 加减乘除)
取消只看楼主 加入收藏
小鱼儿c
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:852
专家分:1317
注 册:2011-4-1
结帖率:95.74%
收藏(2)
 问题点数:0 回复次数:2 
小鱼儿大数运算(前段时间写的 加减乘除)
因为最近论坛交流的气氛太那个,所以贴这个我发到自己空间的文章。其实不怎么想发的,
因为这个代码没有怎么注释,又看到我刚刚的发的那篇补码的文章。觉得用我这种方法现的没有太多技术含量,


大数运算主要是用到数组
加减用到是竖式运算。
除法是转换为减法。。

以后再修改代码加上注释。。

效率没有很科学的测试,但速度人来测试还是蛮快的

big.h

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#define MAX_BIG 200

using namespace std;

typedef struct tagBig
{
 char num[MAX_BIG];
 int flag; //flag > 0 代表正数 反之为
}Big;

void Init(char *n,int flag,Big* n1);
void ReStr(char* str1,char* str2);
void Add(Big n1,Big n2,Big *Result);
void Sub(Big n1,Big n2,Big * Result);
void Mul(Big n1,Big n2,Big * ReSult);
void Dul(Big n1,Big n2,Big * ReSult);
void Mod(Big n1,Big n2,Big * ReSult);

int CompareBig(Big n1,Big n2); //比较2个数的大小 返回一 则为大于 反之小于
void PrinBig(Big *n); //输去大数字
void DelZero(char* str); //除掉多余的0
void DelLastSero(char* str); //除掉最后一个0

 

big.cpp

#include "big.h"


void DelZero(char* str)
{
 int len = strlen(str);
 if(NULL == str || 0 == len)
 {
  return;
 }

 for(int i = len -1 ; i >= 0; i--)
 {
  if(str[i]=='0')
  {
   str[i] = '\0';
  }
  else
  {
   break;
  }
 }
}

void DelLastSero(char* str)
{
 int len = strlen(str) - 1;
 if('0' == str[len])
 {
  str[len] = '\0';
 }

}
void PrinBig(Big *n)
{
 if(n!=NULL)
 {
  if(n->flag ==1)
  {
   puts(n->num);
  }
  else
  {
   //puts("....");
   printf("-%s",n->num);
  }
 }
}

int CompareBig(Big n1,Big n2)
{
 if(n1.flag ==1 && n2.flag == 0)
 {
  return 1;
 }
 
 if(n1.flag == 0 && n2.flag == 1)
 {
  return 0;
 }

 //当2个数的符号是一样的时候

 //当符号都为整数的时候
 if(n1.flag == 1)
 {
  if(strlen(n1.num)>strlen(n2.num))
  {
   return 1;
  }
  else
   if(strlen(n1.num)<strlen(n2.num))
   {
    return 0;
   }
   else
   {
    for(int i = 0; i< strlen(n1.num); i++)
    {
     if(n1.num[i]>n2.num[i])
     {
      return 1;
     }
     else
      if(n1.num[i]<n2.num[i])
      {
       return 0;
      }
    }
    return -1; //这里是2个数字相等于的时候
   }
   
 }
 else
  if(n1.flag == 0)
  {
   if(strlen(n1.num)>strlen(n2.num))
   {
    return 0;
   }
   else
    if(strlen(n1.num)<strlen(n2.num))
    {
     return 1;
    }
    else
    {
     for(int i = 0; i< strlen(n1.num); i++)
     {
      if(n1.num[i]>n2.num[i])
      {
       return 0;
      }
      else
       if(n1.num[i]<n2.num[i])
       {
        return 1;
       }
     }
     return -1; //这里是2个数字相等于的时候
   }
  }
  return 1; //其实这个没有什么用 但编译器有一个警告 我就加了这个
 
}

void Init(char *n,int flag,Big* n1)
{
 strcpy(n1->num,n);
 n1->flag = flag;
}

void ReStr(char* str1,char* str2)
{
 int n =0;
 for(int i = strlen(str1)-1; i >=0; i--)
 {
  str2[n++] = str1[i];
 }
 str2[n] = '\0';
}

void Add(Big n1,Big n2,Big *Result)
{
 int len1 = strlen(n1.num)-1;
 int len2 = strlen(n2.num)-1;
 int jw = 0; //进位大小
 int l,k,re;
 char r1[MAX_BIG];
 char r2[MAX_BIG];
 char r3[MAX_BIG]; //申明一个保存结果的数组 但长度也是有限的
 int len = len1>len2?len1:len2;
 if(strcmp(n1.num,"0") == 0)
 {
  *Result = n2;
  return;
 }

 if(strcmp(n2.num,"0") == 0)
 {
  *Result = n1;
  return;
 }
 strcpy(r1,n1.num);
 strcpy(r2,n2.num);
 if(n1.flag==n2.flag)//同为相同符号
 {
  //puts("同为正数处理");
  for(int i = 0; i <= len; i++)
  {
   l = r1[len1]-48;
   k = r2[len2]-48;
   if(i > strlen(n1.num)-1)
    l =0;
   if(i > strlen(n2.num)-1)
    k =0;
   re = l + k + jw;
   if(re >= 10)
   {
    re = re%10;
    jw = 1;
   }
   else
   {
    jw = 0;
   }
   r3[i] = re + 48;
   len1--;
   len2--;
  }
  if(jw)
  {
   r3[i] = '1';
   r3[i+1] = '\0';
  }
  else
  {
   r3[i] = '\0';
  }
  char s[MAX_BIG];
//   puts("怎么了啊");
//   puts(r3);
//   DelZero(r3);
//   puts(r3);
//
//   puts("是这里吗");
//   getchar();
  
  
  ReStr(r3,s);
  Result->flag = n1.flag;
  strcpy(Result->num,s);
 }
 else
 {
  //进行减号运算
  //因为肯定是不同的符号
  //把他们变成正数来进行比较
  //因为减法在要大数减小数的时候好进行运算
  //否者要考虑别的特殊情况。
  //所以我们判断他们的数字大小是很重要的
  Big b;
  if(n1.flag == 0)
  {
   b.flag = 1;
   strcpy(b.num,n1.num);
   Sub(b,n2,Result);
   if(CompareBig(b,n2)==1)
   {
    Result->flag = 0;
   }
   else
   {
    Result->flag = 1;
   }
  }
  else
  {
   b.flag = 1;
   strcpy(b.num,n2.num);
   Sub(n1,b,Result);
   if(CompareBig(n1,b))
   {
    Result->flag = 1;
   }
   else
   {
    Result->flag = 0;
   }
  }
  
 }
}

void Sub(Big n1,Big n2,Big * Result)
{
 char str1[MAX_BIG];
 char str2[MAX_BIG];
 char str3[MAX_BIG];
 int jw = 0;
 int flag; //存放第二个数字减的时候的符号

 if(n2.flag)
 {
  flag = 0 ;
 }
 else
 {
  flag = 1;
 }
 
 int l,k,re;
 strcpy(str1,n1.num);
 strcpy(str2,n2.num);

 int len1 = strlen(str1)-1;
 int len2 = strlen(str2)-1;
 int len = len1>len2?len1:len2;

 if(CompareBig(n1,n2) == -1)
 {
  //puts("不是在这里吗");
  Result->flag = 1;
  strcpy(Result->num,"0");
  return;
 }

 if(flag == n1.flag)
 {
  
  n1.flag = 1;
  n2.flag = 1;
  Add(n1,n2,Result);
  Result->flag = flag;
  return;
 }
 else
 {
   for(int i = 0; i <= len ; i++)
   {
    l = str1[len1] -48;
    k = str2[len2] - 48;


    if(i > strlen(n1.num)-1)
    {
     l = 0;
    }

    if(i > strlen(n2.num)-1)
    {
     k = 0;
    }

    if(CompareBig(n1,n2) == 1)
    {   
     re = l - k - jw;
    }
    else
    {
     re = k - l - jw;
    }

    //printf("l %d k %d\n re %d",l,k,re);
    //getchar();
    if(re<0)
    {
     re += 10;
     jw = 1;
    }
    else
    {
     jw = 0;
    }
    str3[i] = re + 48;//把结果转换成字符输入到str3数组中
    len1--;
    len2--;
   }
   str3[i] = '\0';
  
 }
 char s[MAX_BIG];
 DelZero(str3);
 ReStr(str3,s);
 strcpy(Result->num,s);

 //相等于在上面已经处理了
 if(CompareBig(n1,n2) == 1)
 {
  Result->flag = 1;
 }
 else
 {
  Result->flag = 0;
 }

}

void Mul(Big n1,Big n2,Big * ReSult)
{
 char str1[MAX_BIG];
 char str2[MAX_BIG];
 //char str3[MAX_BIG];//存放结果
 char temp[MAX_BIG];
 Big *date;

 memset(temp,0,sizeof(temp));

 int l,k,re; //存放数字的
 int jw = 0;
 int n = 0,m = 0;

 Big t1,t2;
 t1.flag = 1;
 t2.flag = 1;
 strcpy(t1.num,n1.num);
 strcpy(t2.num,n2.num);
 


 if(CompareBig(n1,n2))
 {
  strcpy(str1,n1.num);
  strcpy(str2,n2.num);
 }
 else
 {
  strcpy(str1,n2.num);
  strcpy(str2,n1.num);
 }

 //把长度的长的放在上面 跟数学里面的竖式运算是一样的
 int len1 = strlen(str1)-1;
 int len2 = strlen(str2)-1;
 
 date = (Big*)malloc(sizeof(Big)*(strlen(str2))); //分配内存 来存取每个乘后的结果

 //int len = len1>len2?len1:len2;

 for(int j = len2; j >= 0; j--)
 {
  l = str2[j] - 48; //l 放竖式下面的
  for(int i = len1; i >= 0; i--)
  {
   k = str1[i] - 48; //k放上面的竖式的
   re = k*l+jw;
   if(re >=10)
   {
    jw = re/10;
    re = re%10;
   }
   else
   {
    jw = 0;
   }
   temp[m++] = re + 48;//保存转换为字符的单个结果
  }
  if(0 == jw)
  {
   temp

&shy; = '\0';
  }
  else
  {
   temp

&shy; = jw + 48;
   temp[m+1] ='\0';
  }

  m = 0;
  char s[MAX_BIG];
  ReStr(temp,s);
  
  for(int kk = 0; kk <(len2 - j); kk++)
  {
   strcat(s,"0");
  }
  strcpy(date[n].num,s);
  //puts(s);
  memset(temp,0,sizeof(temp));

  date[n].flag = 1; //正负没有关系
  n++;
 }

 Big b;
//  for(int kk =0; kk <strlen(str2); kk++)
//  {
//   printf("%s\n",date[kk].num);
//  }
 b.flag = 1;
 strcpy(b.num,"0");
 ReSult->flag = 1;
 for(int i = 0; i <=len2; i++)
 {
  Add(b,date[i],ReSult);
  b = *ReSult;

 }
 if(n1.flag == n2.flag)
 {
  ReSult->flag = 1;
 }
 else
 {
  ReSult->flag = 0;
 }

 if(strcmp(ReSult->num,"0") == 0)
 {
  ReSult->flag = 1;
 }
 free(date);
}

//对0处理减号 除号都要进行处理,现在还没有处理啊
void Dul(Big n1,Big n2,Big * ReSult)
{
 char str1[MAX_BIG];
 char str2[MAX_BIG];
 char str3[MAX_BIG];
 
 memset(str2,0,sizeof(str2));
 memset(str3,0,sizeof(str3));
 
 int flag;
 if(n1.flag == n2.flag)
 {
  flag = 1;
 }
 else
 {
  flag = 0;
 }
 n1.flag = 1;
 n2.flag = 1;
 strcpy(str1,n1.num);
 strcpy(str2,n2.num);

 //int l,k,re; //存放数字
 if(strcmp(n2.num,"0") == 0)
 {
  puts("除数不能为0");
  exit(3);
 }

 if(CompareBig(n1,n2) == 0)//小于
 {
  Init("0",1,ReSult);
  return;
 }

 if(CompareBig(n1,n2) == -1) //相等
 {
  
  Init("1",1,ReSult);
  ReSult->flag = flag;
  return;
 }

 int len1 = strlen(str1) - 1;//这里长度减一只是为了直接移到数组的末尾
 int len2 = strlen(str2) - 1;

 int cl = len1 - len2; //被除数和除数的长度的差值
 for(int i = 0; i < cl; i++)
 {
  strcat(str2,"0");
 }

 Big t1,t2; //存放现在的被除数和除数
 
 t1 = n1;
 t1.flag = 1;

 t2.flag = 1;
 strcpy(t2.num,str2);

 int len = strlen(str2) - 1; //放除数现在的长度
 
 Big one;
 Init("1",1,&one);

 Big quotient;
 Big Re;
 Init("0",1,&quotient);
 Init("0",1,&Re);

 for(int nl = strlen(t2.num) -1 ; nl >=len2; nl--)
 {

  if(CompareBig(t1,t2) == 1)//当被除数大于被除数的时候
  {

  while(1)//进行一次中减法运算
  {
   Sub(t1,t2,&t1);
   //printf("相减的结果 %s\n",t1.num);
   if(t1.flag == 0)
   {
    strcpy(t1.num,str3);
    t1.flag = 1;
    break;
   }
   if(0 !=t1.flag)//当相减后的结果不为负数的时候进行 商自加一
   {
    //quotient++;
    Add(quotient,one,&quotient);//进行商的运算
   }
   if(0 == strcmp(t1.num,"0")) //当相减的结果为0的时候
   {
    int kk =(strlen(t2.num)-1)-len2;
    for(int ni = 0; ni <kk; ni++)
    {
     strcat(quotient.num,"0");
    }
    printf("商111 %s\n",quotient.num);
    Add(Re,quotient,&Re);
    //printf("ii %s\n",Re.num);
    ReSult->flag = 1;
    *ReSult = Re;
    return;
   }
   
   strcpy(str3,t1.num);
   
  }//进行一次运算后 然后再进行特殊处理
   int kk =(strlen(t2.num)-1)-len2;
   for(int ni = 0; ni <kk; ni++)
   {
    strcat(quotient.num,"0");
   }
  
  Add(Re,quotient,&Re);
  Init("0",1,&quotient);
  }
  DelLastSero(t2.num);//除数删除一位
 }
 ReSult->flag = flag;
 *ReSult = Re;

}

void Mod(Big n1,Big n2,Big * ReSult)
{

 char str1[MAX_BIG];
 char str2[MAX_BIG];
 char str3[MAX_BIG];
 
 memset(str2,0,sizeof(str2));
 memset(str3,0,sizeof(str3));
 
 int flag = 1;
 n1.flag = 1;
 n2.flag = 1;
 strcpy(str1,n1.num);
 strcpy(str2,n2.num);

 //int l,k,re; //存放数字
 if(strcmp(n2.num,"0") == 0)
 {
  puts("除数不能为0");
  exit(3);
 }

 if(n1.flag*n2.flag == 0)
 {
  puts("Mod 不能为负数");
  exit(3);
 }

 if(CompareBig(n1,n2) == 0)//小于
 {
  *ReSult = n1;
  return;
 }

 if(CompareBig(n1,n2) == -1) //相等
 {
  
  Init("0",1,ReSult);
  //ReSult->flag = flag;
  return;
 }

 int len1 = strlen(str1) - 1;//这里长度减一只是为了直接移到数组的末尾
 int len2 = strlen(str2) - 1;

 int cl = len1 - len2; //被除数和除数的长度的差值
 for(int i = 0; i < cl; i++)
 {
  strcat(str2,"0");
 }

 Big t1,t2; //存放现在的被除数和除数
 
 t1 = n1;
 t1.flag = 1;

 t2.flag = 1;
 strcpy(t2.num,str2);

 int len = strlen(str2) - 1; //放除数现在的长度
 
 Big one;
 Init("1",1,&one);

 Big quotient;
 Big Re;
 Init("0",1,&quotient);
 Init("0",1,&Re);

 for(int nl = strlen(t2.num) -1 ; nl >=len2; nl--)
 {

  if(CompareBig(t1,t2) == 1)//当被除数大于被除数的时候
  {

  while(1)//进行一次中减法运算
  {
   Sub(t1,t2,&t1);
   //printf("相减的结果 %s\n",t1.num);
   if(t1.flag == 0)
   {
    strcpy(t1.num,str3);
    t1.flag = 1;
    break;
   }
   if(0 !=t1.flag)//当相减后的结果不为负数的时候进行 商自加一
   {
    //quotient++;
    Add(quotient,one,&quotient);//进行商的运算
   }
   if(0 == strcmp(t1.num,"0")) //当相减的结果为0的时候
   {
    int kk =(strlen(t2.num)-1)-len2;
    for(int ni = 0; ni <kk; ni++)
    {
     strcat(quotient.num,"0");
    }
    //printf("商111 %s\n",quotient.num);
    //Add(Re,quotient,&Re);
    //printf("ii %s\n",Re.num);
    ReSult->flag = 1;
    *ReSult = t1;
    return;
   }
   
   strcpy(str3,t1.num);
   
  }//进行一次运算后 然后再进行特殊处理
   int kk =(strlen(t2.num)-1)-len2;
   for(int ni = 0; ni <kk; ni++)
   {
    strcat(quotient.num,"0");
   }
  
  Add(Re,quotient,&Re);
  Init("0",1,&quotient);
  }
  DelLastSero(t2.num);//除数删除一位
 }
 ReSult->flag = flag;
 *ReSult = t1;
}
搜索更多相关主题的帖子: 测试 文章 include 小鱼儿 
2012-03-26 14:25
小鱼儿c
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:852
专家分:1317
注 册:2011-4-1
收藏
得分:0 
回复 2楼 laoyang103
老杨 你是知道 我对算法 不是很感兴趣。
只要能到达我写那个程序的速度就OK 了。

看你能不把一个发广告的人删了 、我貌似没有找到。
闪了 看书去了。
等下还要考什么思想的东西。。。

用心做一件事情就这么简单
2012-03-26 14:36
小鱼儿c
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:852
专家分:1317
注 册:2011-4-1
收藏
得分:0 
回复 7楼 NoSoul
以后写的话 再写

用心做一件事情就这么简单
2012-03-26 18:54
快速回复:小鱼儿大数运算(前段时间写的 加减乘除)
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.018990 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved