关闭

大数类程序(zz)

标签: iostreamdeletestructclass测试c
619人阅读 评论(0) 收藏 举报
分类:

 文章来源: http://bbs.tarena.com.cn/topic.cgi?forum=2&topic=1782 

整理了一下, 并为larnum类中逻辑运算符函数添加返回值类型:bool , 并在VS2005下测试过. 分三个文件存放:

Bignum.h  // 声明大数类larnum

Bignum.cpp // 实现class larnum

testBignum.cpp // 在main中测试class larnum

******************************  Bignum.h  **********************************

/*******************************************
**Header file of class large intergal number
**Used to calculate accurately
**File name: larnum.h
**Designed by Krizalid on Nov 12th 2004
**Latest edition on Apr 16th 2005
******************************************
*/

//#ifndef LARGE_NUMBER_H
//#define LARGE_NUMBER_H
#include <iostream>
#include 
<memory.h>
#include 
<stdlib.h>
using namespace std;

struct divided;   //声明商和余数的结构体
class larnum
{
public:
    larnum ()   
//无参数构造函数
    {
        sign 
= false
        digit 
= new short(0); 
        len 
= 1;
    }
 // larnum

    larnum (
bool n,short b,short *a);   //逐个输入成员的构造函数
    larnum (char *c);   //字符串参数构造函数
    larnum (int n);   //整型变量构造函数
    larnum (larnum & n);   //拷贝构造函数
    ~larnum(){delete []digit;}   //析构函数
    friend ostream & operator << (ostream & out,larnum & n);   //输出符重载
    friend istream & operator >> (istream & in,larnum & n);   //输入符重载
    
    
short getlen() //取长度
    {
        
return len;
    }
   
  
    larnum 
& operator = (larnum & b);   //运算符重载
    larnum operator = (int b);
    friend larnum abs (larnum n);
    friend larnum 
operator + (larnum a,larnum b);
    friend larnum 
operator - (larnum a,larnum b);
    friend larnum 
operator - (larnum & a);
    friend larnum 
operator * (larnum a,larnum b);
    friend larnum 
operator / (larnum a,larnum b);
    friend larnum 
operator % (larnum a,larnum b);
    friend larnum power (larnum a,
int n);
    friend larnum 
operator ++ (larnum & a);
    friend larnum 
operator ++ (larnum & a,int);
    friend larnum 
operator -- (larnum & a);
    friend larnum 
operator -- (larnum & a,int);
    friend 
bool operator ! (const larnum & a);
    friend 
bool operator == (const larnum & a,const larnum & b);
    friend 
bool operator != (const larnum & a,const larnum & b);
    friend 
bool operator < (larnum a,larnum b);
    friend 
bool operator > (larnum a,larnum b);
    friend 
bool operator <= (larnum a,larnum b);
    friend 
bool operator >= (larnum a,larnum b);
    friend larnum 
operator += (larnum & a,larnum b);
    friend larnum 
operator -= (larnum & a,larnum b);
    friend larnum 
operator *= (larnum & a,larnum b);
    friend larnum 
operator /= (larnum & a,larnum b);
    friend larnum 
operator %= (larnum & a,larnum b);
    friend 
void swap(larnum & a,larnum & b);

private:
  friend divided divide (larnum 
& a,larnum & b);   //可同时返回商和余数的除法函数
  short *digit;   //指向最低位数的指针
  int len;   //长度
  bool sign;   //符号,false为正,true为负
}
;

//定义商和余数的结构体
struct divided
{
    larnum p,r;
}
;

 

******************************  Bignum.cpp  **********************************

/************************************
 *文件名:Bignum.cpp
 *功能:class larnum 的实现
 *创建日期:2007-9-28
***********************************
*/


#include 
"Bignum.h"

//larnum类的实现
larnum::larnum(bool n,short b,short *a)
{
  sign 
= n;
  len 
= b;
  digit 
= new short [b];
  
for (short i = 0;i < b;i++)
     digit[i] 
= a[i];
}


larnum::larnum (
char *c)
{
    
int i;
    
char *= c;
    
if (*== '-'
    
{
        sign 
= true;   
        d
++;
    }

    
else
    
{
        sign 
= false;
         
        
if (*== '+'
            d
++;
    }

    
for (i = 0; (*d); d++)
        
if (*>= '0' && *<= '9'
            i
++;
      
    len 
= i;
    digit 
= new short[i];
    
for (i = 0;d >= c;d--)
        
if (*>= '0' && *<= '9')
        
{
            digit[i] 
= *- '0';
            i
++;
         }


    
while (!digit[len - 1]) //判断首位是否为零并作出相应处理
        len--;   
    
    
if (len <= 0)
    
{
        len 
= 1
        sign 
= false;
    }

}
 // larnum

larnum::larnum(
int n)
{
    
if (n >= 0
        sign 
= false;
    
else 
    
{
        sign 
= true
        n 
= -n;
    }

    
int m = n;
    
for (len = 0;n;len++,n /= 10)
        ;
    
if (!len) 
        len
++;
    
    digit 
= new short[len];
    
for (short i = 0;i < len;i++)
    
{
        digit[i] 
= m % 10;
        m 
/= 10;
    }

}


larnum::larnum (larnum 
& n)
{
    sign 
= n.sign;
    len 
= n.len;
    digit 
= new short[len];
    memcpy(digit,n.digit,
2 * len);
}



larnum 
& larnum::operator = (larnum & b)
{
    sign 
= b.sign;
    len 
= b.len;
    digit 
= new short[len];
    memcpy(digit,b.digit,
2 * len);
  
    
return *this;
}


larnum larnum::
operator = (int b)
{
    larnum c(b);
    
*this = c;
  
    
return *this;
}


larnum abs (larnum n)
{
    n.sign 
= 0;  
    
    
return n;
}


bool operator ! (const larnum & a)
{
    
if ((a.len == 1&& !*a.digit) 
        
return true;
    
else 
        
return false;
}


ostream 
& operator << (ostream & out,larnum & n)
{
    
if (n.sign) 
        
out <<"-";
    
for(short i = n.len - 1;i >= 0;i--)
        
out <<n.digit[i];

    
return out;
}


istream 
& operator >> (istream & in,larnum & n)
{
/*   const int N = 30;PUl
  char *k = new char[N];;"fIL
  char temp, *p = k;F0Mq
  int l = 1;L$j6,E
  while ((temp = cin.get()) != ' ');d
  {N,
     if (!(l % N))T'
     {ohJ
        k = new char[l + N];]5%2IX
        memcpy (k,p,sizeof(short) * l);T%5
        delete []p;Cg
        p = k;$Pt:Q3
     }w]2
     k[l - 1] = temp;~`BA
     l++;F
  }=TO[h
  n = larnum(k);M1%u"1
  return in;
*/

  
    
char k[256];
    
in >>k;
    n 
= larnum (k);
  
    
return in;
}


//交换函数
inline void swap(larnum & a,larnum & b)
{
    
bool sign = a.sign;
    a.sign 
= b.sign;
    b.sign 
= sign;
    
short *digit = a.digit;
    
int len = a.len;
    a.digit 
= b.digit;
    b.digit 
= digit;
    a.len 
= b.len;
    b.len 
= len;
}


bool operator == (const larnum & a,const larnum & b)
{
    
if (a.sign ^ b.sign) 
        
return false;
  
    
if (a.len != b.len) 
        
return false;
  
    
for (short i = 0;i <= a.len - 1;i++)
        
if (a.digit[i] != b.digit[i]) 
            
return false;
    
    
return true;
}


bool operator != (const larnum & a,const larnum & b)
{
  
if (a == b) 
      
return false;
  
else 
      
return true;
}


inline larnum 
operator - (larnum & a)
{
    
if (a.len == 1 && !(a.digit[0])) 
        
return a;
    
else if (a.sign) 
        a.sign 
= false;
    
else 
        a.sign 
= true;

    
return a;
}


bool operator > (larnum a,larnum b)
{
    
switch (2 * a.sign + b.sign)   //把符号组合看成二进制数,方便控制,下同w22p.
    {
    
case 1:
        
return true;
    
case 2:
        
return false;
    
case 3:   //若均为负则交换,下面比较的实际上是绝对值NbZ/C
        swap (a,b);
    
case 0:
        
if (a.len > b.len)
            
return true;   //比较长度cX2
        else if (a.len < b.len)
            
return false;
        
else
        
{
            
for (int i = a.len - 1;i >= 0;i--)   //逐位比较0
            {
                
if (a.digit[i] > b.digit[i]) 
                    
return true;
                
                
if (a.digit[i] < b.digit[i])
                    
return false;
            }

        }
// else

        
return false;
    }
 // switch
}


bool operator < (larnum a,larnum b)
{
    
return !(a > b || a == b);
}


bool operator >= (larnum a,larnum b)
{
    
return (a > b || a == b);
}


bool operator <= (larnum a,larnum b)
{
    
return !(a > b);
}


larnum 
operator + (larnum a,larnum b)
{
    larnum c;
    
short i,l,pro;
    
switch (2 * a.sign + b.sign)
    
{
    
case 0:
    
case 3:   //绝对值相加
        c.sign = a.sign;
        
if (a.len < b.len) 
            swap(a,b);
        l 
= a.len;
        pro 
= 0;   //进位值
        c.digit = new short[l + 1];
        
for (i = 0;i <= l - 1;i++)
        
{
            c.digit[i] 
= a.digit[i] + pro + (i < b.len?b.digit[i]:0);   //判断i是否越界
        
            
if (c.digit[i] > 9)   //判断进位并作出相应处理
            {
                pro 
= 1;
                c.digit[i] 
-= 10;
            }

            
else 
                pro 
= 0;
        }
 // for
        
        
if (pro)   //根据最后进位值确定结果的长度
        {
            c.digit[l] 
= 1;
            c.len 
= l + 1;
        }

        
else 
            c.len 
= l;
        
        
return c;
    
case 2:
        swap(a,b);
    
case 1:   //绝对值相减
        if (-> a)   //以下仅适用于|a| >= |b|,若|a| < |b|则交换
        {
            c.sign 
= true;
            swap (a,b);
        }

        
else 
            c.sign 
= false;
     
        l 
= a.len;
        pro 
= 0;   //退位值
        c.digit = new short[l];
     
        
for (i = 0;i <= l - 1;i++)
        
{
            c.digit[i] 
= a.digit[i] + pro - (i < b.len? b.digit[i]:0);   //判断i是否越界
            if (c.digit[i] < 0)   //判断退位并作出相应处理 
            {
                pro 
= -1;
                c.digit[i] 
+= 10;
            }

            
else
                pro 
= 0;
        }

     
        
while (!c.digit[l - 1]) //确定结果的长度
            l--;   
     
        
if (!l)  
            l 
= 1;
     
        c.len 
= l;
     
        
return c;
    }
 // switch
}


larnum 
operator += (larnum & a,larnum b)
{
    a 
= a + b; 
    
    
return a;
}


larnum 
operator - (larnum a,larnum b)
{
    
return a + (-b);
}


larnum 
operator -= (larnum & a,larnum b)
{
    a 
= a + (-b); 
    
return a;
}


larnum 
operator * (larnum a,larnum b)
{
    
int i, j;

    
if (!|| !b) //对因数有零的先处理
        return 0;   
  
    larnum c;
    
int pro = 0;   //进位值
    c.sign = a.sign ^ b.sign;   //确定符号
    short l = a.len + b.len;
    c.digit 
= new short[l];
    memset(c.digit,
0,l * sizeof(short));   //对结果数组清零
    for (i = 0; i < a.len; i++)
    
{
        
for (j = 0; j < b.len; j++)
        
{
            c.digit[i 
+ j] += (a.digit[i] * b.digit[j] + pro);
            pro 
= c.digit[i + j] / 10;   //进位处理
            c.digit[i + j] %= 10;
        }

     
        c.digit[i 
+ j] = pro;
        pro 
= 0;
    }

  
    
if (c.digit[l - 1]) //确定结果的长度 
        c.len = l;   
    
else 
        c.len 
= l - 1;
  
    
return c;
}


larnum 
operator *= (larnum & a,larnum b)
{
    a 
= a * b; 
    
return a;
}


//用模拟人工笔算实现除法5E
divided divide (larnum & a,larnum & b)
{
    divided c;
    c.r 
= c.p = 0;
    
    
if (!b)   //判断除零异常
        throw b;      
    
    
if (abs(b) > abs(a))   //预先处理处理被除数绝对值小于除数绝对值的情况
    {
        c.r 
= a;  
        
return c;
    }

  
    
bool rsign = a.sign;   //预先判断和保存结果的符号,以下用绝对值来除
    c.p.sign = a.sign ^ b.sign;
    a 
= abs(a);
    b 
= abs(b);
    larnum temp;         
//定义当前除到的数
    temp.sign = false;
    temp.len 
= b.len;
    temp.digit 
= a.digit + a.len - b.len;   //指向当前除到的数的末位
    c.p.len = a.len - b.len + 1;
    
if (temp < b)
    
{
         temp.len
++;
        temp.digit
--;
        c.p.len
--;
    }

    
    c.p.digit 
= new short[c.p.len];   //分配商指针
    memset (c.p.digit,0,c.p.len * sizeof(short));   //给商指针置零
    larnum b_five = b * 5;   //定义用于减法的除数的倍数
    larnum b_three = b * 5;
    
for (int i = c.p.len - 1;i >= 0;i--)
    
{
        temp.digit 
= a.digit + i;
        temp.len 
= a.len - i;
     
        
//用这样的减法,最多四次就能除一位e1[xB
        if (temp >= b_five)
        
{
            c.p.digit[i] 
+= 5;
            temp 
-= b_five;
            memcpy (a.digit 
+ i,temp.digit,temp.len * sizeof(short));
            a.len 
= temp.len + i;
            temp.digit 
= a.digit + i;
        }

        
if (temp >= b_three)
        
{
            c.p.digit[i] 
+= 3;
            temp 
-= b_three;
            memcpy (a.digit 
+ i,temp.digit,temp.len * sizeof(short));
            a.len 
= temp.len + i;
            temp.digit 
= a.digit + i;
        }


        
while (temp >= b)
        
{
            c.p.digit[i]
++;
            temp 
-= b;
            memcpy (a.digit 
+ i,temp.digit,temp.len * sizeof(short));
            a.len 
= temp.len + i;
            temp.digit 
= a.digit + i;
        }

     
        
while (!a.digit[a.len - 1])  //更新a的长度
            a.len--;   
    }
 // for

    
if (!temp.len)
      temp.len
++;
  
    c.r 
= temp;   //最后剩下的就是余数
    temp.digit = new short(0);   //因temp和a用的是同一块内存,只有这样才能避免析构时不出错
    c.r.sign = rsign;   //商的符号
  
    
return c;
}


larnum 
operator / (larnum a,larnum b)
{
    divided c;
  
    
try    //捕捉除零异常
    {
        c 
= divide(a,b);
    }
  
    
catch(larnum)
    
{
        cerr
<<"ERROR: Exception of divided by zero. End. ";
        exit(
1);
    }

  
    
return c.p;
}


larnum 
operator /= (larnum & a,larnum b)
{
    a 
= a / b;  
    
    
return a;
}


larnum 
operator %= (larnum & a,larnum b)
{
    a 
= a % b;  
    
    
return a;
}


larnum 
operator % (larnum a,larnum b)
{
    divided c;
  
    
try    //捕捉除零异常
    {
        c 
= divide(a,b);
    }
  
    
catch(larnum)
    
{
        cerr
<<"ERROR: Exception of divided by zero. End. ";
        exit(
0);
    }

  
    
return c.r;
}


larnum power (larnum a,
int n)
{
    
if (n < 0)
        
return 0;
  
    larnum b 
= 1;
 
    
for (int i = 0;i < n;i++
        b 
*= a;
  
    
return b;
}
 

larnum 
operator ++ (larnum & a)
{
    
int i;
    
    
switch (a.sign)
    
{
    
case 0:
        
for (i = 0;i < a.len;i++)
        
{
            a.digit[i]
++;
            
if (a.digit[i] != 10)   //只要没有进位就可以马上返回 
                return a; 
            
else 
                a.digit[i] 
= 0;
        }
 // for

        delete []a.digit;   
//如果每一位都是9才分配新的内存
        a.len++;
        a.digit 
= new short[a.len];
        memset(a.digit,
0,a.len * sizeof(short));
        a.digit[a.len 
- 1= 1;
     
        
return a;
    
case 1:
        
if (a.len == 1)   //预先处理一位数的情形
        {
            
if (!(--a.digit[0])) 
                a.sign 
= 0;
            
return a;
        }

     
        
for (i = 0;i < a.len - 1;i++)
        
{
            a.digit[i]
--;
            
if (a.digit[i] != -1
                
return a;
            
else 
                a.digit[i] 
= 9;
        }

        
        
if (!(--a.digit[i])) 
            a.len
--;
     
        
return a;
    }
 // switch
}


larnum 
operator ++ (larnum & a,int)
{
    larnum b 
= a;
    
++a;
  
    
return b;
}


larnum 
operator -- (larnum & a)
{
    larnum b 
= -a;
    
++b; 
  
    
return a = -b;
}


larnum 
operator -- (larnum & a,int)
{
    larnum b 
= a;
    
--a;
  
    
return b;
}


/*
larnum::larnum (char *c)
{
    char *d = c;
    int i;

    if (*d == '-') 
    {
        sign = true;   
        d++;
    }
    else
    {
        sign = false;
        if (*d == '+') 
            d++;
    }
 
    for (i = 0; (*d); d++)
        if (*d >= '0' && *d <= '9') 
            i++;
 
    len = i;
    digit = new short[i];
 
    for (i = 0;d >= c;d--)
        if (*d >= '0' && *d <= '9')
        {
            digit[i] = *d - '0';
            i++;
        }
 
    while (!digit[len - 1]) //判断首位是否为零并作出相应处理
        len--;   
 
    if (len <= 0) 
    {
        len = 1; 
        sign = false;
    }
}
*/

 

******************************  testBignum.cpp **********************************

/************************************
 *文件名:testBignum.cpp
 *功能:测试class larnum
 *创建日期:2007-9-28
***********************************
*/

#include 
<iostream>
#include 
"Bignum.h"
using namespace std;

int main()
{
    larnum a,b;
  
    cout 
<<"Please input LargeNumber a: ";
    cin 
>>a;
    
    cout 
<<"Please input LargeNumber b: ";
    cin 
>>b;
  
    
int n;
    cout 
<<"Please input n: ";
    cin 
>> n;
  
    cout 
<< "a = " << a << endl;
    cout 
<<"b = "<<b<<endl;
    cout 
<< "Length of a: " << a.getlen() << endl;
    cout 
<<"Length of b: "<<b.getlen()<<endl;
    cout 
<<"a + b = "<<+ b<<endl;
    cout 
<<"a - b = "<<- b<<endl;
    cout 
<<"a * b = "<<* b<<endl;
    cout 
<<"a / b = "<</ b<<endl;
    cout 
<<"a mod b = "<<% b<<endl;
    cout 
<< "a ^ " << n << " = " << power(a,n) <<endl; 

    
return 0;
}
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:110717次
    • 积分:1215
    • 等级:
    • 排名:千里之外
    • 原创:36篇
    • 转载:8篇
    • 译文:0篇
    • 评论:15条
    纯属八卦
    名家博客