30/09/2018, 16:45

Bignum: nhờ sửa lỗi phát sinh trong C++

// BIGNUM.cpp : Defines the entry point for the console application.
//

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

//Khai báo hằng
#define MAXDIGITS 100 /* maximum length */
#define PLUS 1 /* positive sign bit */
#define MINUS -1 /* negative sign bit */

//Khai báo cấu trúc
typedef struct {
	char digits[MAXDIGITS]; /* the number */
	int signbit; /* PLUS or MINUS */
	int lastdigit; /*index of high-order digit*/
}bignum;
// khai báo hàm
void print_bignum(bignum n);
void scan_bignum(bignum &n);
void zero_justify(bignum &n);
void add_bignum(bignum &a, bignum &b, bignum &c);
void subtract_bignum(bignum a, bignum b, bignum &c);
int compare_bignum(bignum &a, bignum &b);
//Một số hàm xử lý
void print_bignum(bignum n)
{
	int i;
	if (n.signbit == MINUS) cout << "-";
	for (i = n.lastdigit; i >= 0; i--)
		cout << int(n.digits[i]); // ép kiểu để ko ra ký tự lạ
	//cout <<endl;
}

int kiemtra(char s[]){
	//ktra ký tự đầu
	if (s[0] != '-' && !isdigit(s[0]))
		return 0;
	//ktra các ký tự tiếp theo
	int len = strlen(s);
	for (int i = 1; i<len; i++)
	if (!isdigit(s[i])) return 0;
	//không phát hiện vi phạm
	return 1;
}

void scan_bignum(bignum &n)
{
	//B1: Nhập chuỗi
	char temp[256];
	cin.getline(temp, 256);
	//B2: Kiểm tra
	if (!kiemtra(temp)){	//không hợp lệ
		//gán bignum = 0
		n.signbit = PLUS;
		n.lastdigit = 0;
		n.digits[0] = 0;
	}
	else {		//hợp lệ. B3: chuyển thành số bignum
		//xét 2 trường hợp
		if (temp[0] != '-'){	//số dương
			n.signbit = PLUS;
			n.lastdigit = strlen(temp) - 1;
			for (int i = 0; i <= n.lastdigit; i++)
				n.digits[i] = temp[n.lastdigit - i] - 48;
		}
		else {				//số âm
			n.signbit = MINUS;
			n.lastdigit = strlen(temp) - 2;
			for (int i = 0; i <= n.lastdigit; i++)
				n.digits[i] = temp[n.lastdigit + 1 - i] - 48;
		}
	}
}
// loại bỏ những số không vô nghĩa
/**/
void zero_justify(bignum &n)
{
	while ((n.lastdigit > 0) && (n.digits[n.lastdigit] == 0))
		n.lastdigit--;
	if ((n.lastdigit == 0) && (n.digits[0] == 0))
		n.signbit = PLUS; /* hack to avoid -0 */
}
//
/**/
int max(int a, int b)
{
	if (a > b) return a;
	return b;
}
void add_bignum(bignum &a, bignum &b, bignum &c)
{
	int carry; /* carry digit */
	int i; /* counter */
	//initialize_bignum(c); // khởi gán cho các chữ số bằng 0
	if (a.signbit == b.signbit) c.signbit = a.signbit;
	else
	{ // cộng 2 số trái dấu
		if (a.signbit == MINUS)
		{
			a.signbit = PLUS;
			subtract_bignum(b, a, c);
			a.signbit = MINUS;
		}
		else
		{
			b.signbit = PLUS;
			subtract_bignum(a, b, c);
			b.signbit = MINUS;
		}
		return;
	}
	c.lastdigit = max(a.lastdigit, b.lastdigit) + 1;
	// điều chỉnh a,b
	for (i = a.lastdigit + 1; i <= c.lastdigit; i++)
		a.digits[i] = 0;
	for (i = b.lastdigit + 1; i <= c.lastdigit; i++)
		b.digits[i] = 0;
	carry = 0;
	for (i = 0; i <= (c.lastdigit); i++) {
		c.digits[i] = (char)
			(carry + a.digits[i] + b.digits[i]) % 10;
		carry = (carry + a.digits[i] + b.digits[i]) / 10;
	}
	zero_justify(c);
}
//
void subtract_bignum(bignum a, bignum b, bignum &c)
{
	int borrow; /* anything borrowed? */
	int v; /* placeholder digit */
	int i; /* counter */
	if ((a.signbit == MINUS) || (b.signbit == MINUS)) {
		b.signbit = -1 * b.signbit;
		add_bignum(a, b, c);
		b.signbit = -1 * b.signbit;
		return;
	}
	if (compare_bignum(a, b) == PLUS)
	{
		subtract_bignum(b, a, c);
		c.signbit = MINUS;
		return;
	}
	c.lastdigit = max(a.lastdigit, b.lastdigit);
	for (i = a.lastdigit + 1; i <= c.lastdigit; i++)
		a.digits[i] = 0;
	for (i = b.lastdigit + 1; i <= c.lastdigit; i++)
		b.digits[i] = 0;
	borrow = 0;
	for (i = 0; i <= (c.lastdigit); i++) {
		v = (a.digits[i] - borrow - b.digits[i]);
		if (a.digits[i] > 0)
			borrow = 0;
		if (v < 0) {
			v = v + 10;
			borrow = 1;
		}
		c.digits[i] = (char)v % 10;
	}
	zero_justify(c);
}
//
int compare_bignum(bignum &a, bignum &b)
{
	int i; /* counter */
	if ((a.signbit == MINUS) && (b.signbit == PLUS)) return(PLUS);
	if ((a.signbit == PLUS) && (b.signbit == MINUS)) return(MINUS);
	if (b.lastdigit > a.lastdigit) return (PLUS * a.signbit);
	if (a.lastdigit > b.lastdigit) return (MINUS * a.signbit);
	for (i = a.lastdigit; i >= 0; i--)
	{
		if (a.digits[i] > b.digits[i])
			return(MINUS * a.signbit);
		if (b.digits[i] > a.digits[i])
			return(PLUS * a.signbit);
	}
	return(0);
}
void digit_shift(bignum n, int d) /* multiply n by 10ˆd */
{

	int i; /* counter */
	if ((n.lastdigit == 0) && (n.digits[0] == 0)) return;
	for (i = n.lastdigit; i >= 0; i--)
		n.digits[i + d] = n.digits[i];
	for (i = 0; i<d; i++) n.digits[i] = 0;
		n.lastdigit = n.lastdigit + d;
}
void multiply_bignum(bignum &a, bignum &b, bignum &c)
{
	bignum row; /* represent shifted row */
	bignum tmp; /* placeholder bignum */
	int i, j; /* counters */
	//initialize_bignum(c);



	row = a;
	for (i = 0; i <= b.lastdigit; i++)
	{
		for (j = 1; j <= b.digits[i]; j++)
		{
			add_bignum(c, row, tmp);
			c = tmp;
		}
		digit_shift(row, 1);
	}
	c.signbit = a.signbit * b.signbit;
	zero_justify(c);
}
void divide_bignum(bignum a, bignum b, bignum &c)
{
	bignum row; /* represent shifted row */
	bignum tmp; /* placeholder bignum */
	int asign, bsign; /* temporary signs */
	int i, j; /* counters */
	//initialize_bignum(c);
	c.signbit = a.signbit * b.signbit;
	asign = a.signbit;
	bsign = b.signbit;
	a.signbit = PLUS;
	b.signbit = PLUS;
	//initialize_bignum(&row);
	//initialize_bignum(&tmp);
	c.lastdigit = a.lastdigit;
	for (i = a.lastdigit; i >= 0; i--) {
		digit_shift(row, 1);
		row.digits[0] = a.digits[i];
		c.digits[i] = 0;
		while (compare_bignum(row, b) != PLUS) {
			c.digits[i] ++;
			subtract_bignum(row, b, tmp);
			row = tmp;
		}
	}
	zero_justify(c);
	a.signbit = asign;
	b.signbit = bsign;
}
int _tmain(int argc, _TCHAR* argv[])
{
	bignum n;
	bignum row; 
	bignum tmp;

	cout << "nhap vao so lon:";
	scan_bignum(n);
	cout << "so lon vua nhap:";
	print_bignum(n);
	cout << endl;
	/////////////////////////////////////

	///////////////////////////////
	bignum a, b, c;
	cout << "nhap vao a=";
	scan_bignum(a);
	cout << "nhap vao b=";
	scan_bignum(b);
	
	subtract_bignum(a, b, c);

	cout << "a+b=";
	print_bignum(c);
	cout << endl;

	cout << "a-b=";
	print_bignum(c);
	cout << endl;

	multiply_bignum(a, b, c);
	cout << "a*b=";
	print_bignum(c);
	cout << endl;
	///////////////////////////////



	return 0;
}
Minh Hoàng viết 18:55 ngày 30/09/2018

lỗi gì vậy bạn? bạn nêu chi tiết được không?

Gió viết 18:51 ngày 30/09/2018

Hàm multiply_bignum của bạn bị sai. Mình sửa lại và chia thành 2 hàm multiply_intmultiply_bignum

  • Hàm digit_shift(bignum n, int d) của bạn truyền bằng value nên không có tác dụng. Sửa lại: digit_shift(bignum&,int d)
void digit_shift(bignum &n, int d) /* multiply n by 10ˆd */
{

    int i; /* counter */
    if ((n.lastdigit == 0) && (n.digits[0] == 0)) return;
    for (i = n.lastdigit; i >= 0; i--)
        n.digits[i + d] = n.digits[i];
    for (i = 0; i<d; i++) n.digits[i] = 0;
        n.lastdigit = n.lastdigit + d;
}

void multiply_int(bignum &a,int b,bignum &c){
    
    int carry=0;
    if(b<0){
        c.signbit=-a.signbit;
        b=-b;
    }else{
        c.signbit=a.signbit;
    }
    for(int i=0;i<=a.lastdigit;++i){
        carry+=a.digits[i]*b;
        c.digits[i]=carry%10;
        carry/=10;
    }
    c.lastdigit=a.lastdigit;
    while(carry){
        c.digits[++c.lastdigit]=carry%10;
        carry/=10;
    }
    zero_justify(c);
    
}
void multiply_bignum(bignum &a,bignum &b,bignum &c){
    bignum tmp1,tmp2;
    // c= 0 
    c.lastdigit=0;
    c.digits[0]=0;
    
    for(int i=b.lastdigit;i>=0;--i){
        digit_shift(c,1);
        multiply_int(a,b.digits[i],tmp1);
        add_bignum(c,tmp1,tmp2);
        c=tmp2;
    }
    c.signbit=a.signbit*b.signbit;
    zero_justify(c);
}
Long Long viết 18:46 ngày 30/09/2018

void digit_shift(bignum &n, int d) /* multiply n by 10ˆd */
{

int i; /* counter */
if ((n.lastdigit == 0) && (n.digits[0] == 0)) return;
for (i = n.lastdigit; i &gt;= 0; i--)
    n.digits[i + d] = n.digits[i];
for (i = 0; i&lt;d; i++) n.digits[i] = 0;
    n.lastdigit = n.lastdigit + d;

}

hi. mình sửa đc rồi ,nhung ham chia thì ko ra, nó bị sai ở vòng lặp nhưng mình ko bít chỗ nào hết

Bài liên quan
0