Thứ Hai, 24 tháng 11, 2014

Xử lý tính toán với 2 số nguyên lớn có thể đến hàng trăm chữ số

Dùng mảng 1 chiểu để lưu trữ
1. Viết 1 chương trình nhập vào 2 số nguyên lớn (có thể đến hàng trăm chữ số)
2. Thực hiện phép toán trên 2 số đó:
a.So sánh
b.cộng
c.trừ
3.Thực hiện phép nhân,phép chia số nguyên lớn đối với số nguên hoặc số nguyên lớn đối với số nguyên lớn(bonus)


Gợi ý:
Nhập vào N1,N2 là 1 dãy kí tự char n1[300]
Chuyển vào mảng số bằng cách-'0'
N1 có 9 kí tự.N2 có 3 kí tự.Gọi chieudaimax là số phần tử của mảng có nhiều phần tử hơn.
N1:123456789
N2:123
N1:
n2:
kq: +
kq: n1 –n2
kq: n2-n1
Cộng: Ta sẽ cộng từng giá trị từ cuối mảng trở về trước. kết quả sẽ được lưu trong mảng kq. Mảng kq sẽ có max+1 phần tử. Và sẽ có biến nhớ để lưu giá trị của từng phép cộng của các phần tử.
Trừ: Từ phép so sánh ta sẽ lấy phần tử lớn trừ phần tử nhỏ, nếu là trường hợp nhỏ trừ lớn sẽ xuất ra dấu – trước kết quả. Ta sẽ có biến nhớ để lưu có mượn hay không?
Nhân: Để đơn giản ta có thể lặp đi lặp lại phép cộng nhiều lần. Ví dụ: a*3 = a+a+a
Chia: Để đơn giản ta có thể dùng phép trừ.
Ví dụ: 16/3
Kiểm tra số 16 có lớn hơn 3 hay không? Nếu không à kq = 0
3*1=3 < 16: tiếp tục lặp cho đến khi được tích >= số bị chia
3*2=6
3*3=9
3*4=12
3*5=15
3*6=18
18>16 à xuất 6-1 = 5

 Demo:

#include <iostream>using namespace std#include <conio.h>class nguyenduong{
private:
    
char x[200];
public:
    
friend istreamoperator>>(istream&,nguyenduong&);
    
friend ostreamoperator<<(ostream&,nguyenduong);
    
friend nguyenduong operator+(nguyenduong,nguyenduong);
    
friend bool operator>(nguyenduong,nguyenduong);
    
friend bool operator>=(nguyenduong,nguyenduong);
    
friend bool operator<(nguyenduong,nguyenduong);
    
friend bool operator<=(nguyenduong,nguyenduong);
    
friend bool operator==(nguyenduong,nguyenduong);
    
friend bool operator!=(nguyenduong,nguyenduong);
};
int xstrlen(char *xau)
{
    
int i=0;
    while (
xau[i])i++;
    return 
i;
}
ostreamoperator<<(ostreamo,nguyenduong x)
{
    return 
o<<x.x;
}
istreamoperator>>(istream &i,nguyenduong &x)
{
    return 
i>>x.x;
}
void chenkitu(char *xau ,int vitri=0char chen='0'//vi tri bat dau tu 0  {
    for (
int i=xstrlen(xau)+1;i>vitri;i--)   xau[i]=xau[i-1];
    
xau[vitri]=chen;
}  
void xoakitu(char *xau,int vitri=0//vi tri bat dau tu 0{
    for(
int i=vitri;i<=xstrlen(xau);i++) xau[i]=xau[i+1];
}
void canbang(char *a,char *b)
{
    
int ai=xstrlen(a),bi=xstrlen(b);
    
char *p=ai>bi?b:a;
    if (
ai!=bi)
        for (
int i=(ai>bi?ai:bi)-xstrlen(p);i>0;i--) chenkitu(p);
    
chenkitu(a);chenkitu(b);
}  
void tong(char *a,char *b,char *s,int i=0)   // bước đệm cho toán tử +, giống như vscanf và scanf vậy{                                              // sử dụng đệ quy để tính tổng 2 chuỗi
    
static int temp=0;
    if (
i<xstrlen(a)) tong(a,b,s,i+1);
    if (
a[i]==NULLs[i]=NULL;
        else
        {
            
s[i]=a[i]+b[i]+temp-'0';
            if (
s[i]>'9's[i]-=10,temp=1;
                else 
temp=0;
        }
}  
nguyenduong operator+(nguyenduong anguyenduong b)
{
    
nguyenduong s;
    
canbang(a.x,b.x);
    
tong(a.x,b.x,s.x);
    
xoakitu(a.x);
    
xoakitu(b.x);
    if (
s.x[0]='0'xoakitu(s.x);
    return 
s;
}
int sosanhf(char *a,char *b,int i=0// a>b trả về 1 , a<b trả về -1 , a==b trả về 0{
    if (
i==xstrlen(a)) return 0;
    else if (
a[i]>b[i]) return 1;
    else if (
a[i]<b[i]) return -1;
    else return 
sosanhf(a,b,i+1);
}
int sosanh(char *a,char *b)
{
    
canbang(a,b);
    
int temp=sosanhf(a,b);
    
xoakitu(a);    xoakitu(b);  
    return 
temp;
}
bool operator>(nguyenduong a,nguyenduong b)
{
    if (
sosanh(a.x,b.x)==1)    return 1;
    else return 
0;
}
bool operator>=(nguyenduong a,nguyenduong b)
{
    if (
sosanh(a.x,b.x)>=0)    return 1;
    else return 
0;
}
bool operator<(nguyenduong a,nguyenduong b)
{
    if (
sosanh(a.x,b.x)==-1)    return 1;
    else return 
0;  
}
bool operator<=(nguyenduong a,nguyenduong b)
{
    if (
sosanh(a.x,b.x)<=0)    return 1;
    else return 
0;  
}
bool operator==(nguyenduong a,nguyenduong b)
{
    if (
sosanh(a.x,b.x)) return 0;
    else return 
1;  
}
bool operator!=(nguyenduong a,nguyenduong b)
{
    if (
sosanh(a.x,b.x))    return 1;
    else return 
0;  
}
void main(void)
    {
        
nguyenduong a,b;
        
cout<<"Nhap vao 2 so nguyen lon : ";
        
cin>>a>>b;
        
cout<<"Tong 2 so la :"<<a+b;
        if (
a>bcout<<a<<" > "<<b;
        
// ok ?

        
system("pause");
    }  

PHƯƠNG PHÁP LẶP ĐƠN



PHƯƠNG PHÁP LẶP ĐƠN
            Giả sử phương trình (1) được đưa về dạng tương đương :
                x = g(x)                                                                                                                                                  2)
từ giá trị xo nào đó gọi là giá trị lặp đầu tiên ta lập dãy xấp xỉ bằng công thức:
                xn= g(x+-1)                                                                                            (3)
với n = 1,2,....
Hàm g(x) được gọi là hàm lặp. Nếu dãy xn ® a khi n ®µ thì ta nói phép lặp (3) hội tụ.





Ta có định lí: Xét phương pháp lặp (3), giả sử :
- [a,b] là khoảng phân li nghiệm a của phương trình (1) tức là của (2)
- mọi xntính theo (3) đều thuộc [a, b]
- g(x) có đạo hàm thoả mãn :
                                                                                                                        (4)
trong đó q là một hằng số thì phương pháp lặp (3) hội tụ
Ta có thể minh hoạ phép lặp trên bằng hình vẽ trên.
Cách đưa phương trình  f(x) = 0 về dạng x = g(x) được thực hiện như sau: ta thấy f(x) = 0 có thể biến đổi thành x = x + lf(x) với l ¹ 0. Sau đó đặt x+lf(x) = g(x) sao cho điều kiện (4) được thoả mãn.
                Ví dụ: xét phương trình 
                                x3+ x - 1000 = 0
Sau bước giải sơ bộ ta có nghiệm x1Î ( 9,10 )
Nếu đưa phương trình về dạng:
                                x = 1000 - x3 = g(x)
thì dễ thấy | g'(x) | > 1 trong khoảng ( 9, 10 ) nên không thoả mãn điều kiện (4)
Chúng ta đưa phương trình về dạng
                                               

thì ta thấy điều kiện (4) được thoả mãn.Xây dựng dãy xấp xỉ
                                               
với xo chọn bất kì trong ( 9, 10 )
                Trên cơ sở phương pháp này chúng ta có các chương trình tính toán sau:
Chương trình giải phương trình exp((1/3)*ln(1000-x)) với số lần lặp cho trước

Chương trình 2-1


//lap don
#include <conio.h>

#include <stdio.h>

#include <math.h>



void main()

  {

                int i,n;

                float x,x0;

                float f(float);

                clrscr();

                printf("Cho so lan lap n = ");

                scanf("%d",&n);

                printf("Cho gia tri ban dau cua nghiem x0 = ");

                scanf("%f",&x0);

                x=x0;

                for (i=1;i<=n;i++)

                  x=f(x);

                printf("Nghiem cua phuong trinh la :%.4f",x);

                getch();

  }

float f(float x)
  {
                float a=exp((1./3.)*log(1000-x));
                return(a);
  }

và chương trình giải bài toán bằng phương pháp lặp với sai số cho trước

Chương trình 2-2


//lap don
#include <conio.h>

#include <stdio.h>

#include <math.h>

void main()

  {

                int i;

                float epsi,x,x0,y;

                float f(float);



                clrscr();

                printf("Cho sai so epsilon = ");

                scanf("%f",&epsi);

                printf("Cho gia tri ban dau cua nghiem x0 = ");

                scanf("%f",&x0);

                x=x0;

                y=f(x);

                if (abs(y-x)>epsi)

                  {

                                x=y;

                                y=f(x);

                  }

                printf("Nghiem cua phuong trinh la %.6f",y);

                getch();

  }



float f(float x)

  {

                float a=exp((1./3.)*log(1000-x));

                return(a);

  }


Cho giá trị đầu xo = 1.Kết quả tính toán x = 9.966555

Bài đăng phổ biến