表达式运算(包含大整数加减乘)

思路:

之前写的乘法有点小问题,现在更正了

普通表达式运算:

采用字符串的形式输入一个表达式和栈结构来存储中间运算结果,可以参照《数据结构(严慧敏)》,依次从字符串中读取字符,如果是数字则读取整个数字,如果是运算符则判断优先级(出栈\压栈\计算)......

 

大整数表达式运算:

与普通的表达式同一个思路,只不过现在的数变成了大整数,所以得自己分别实现大整数的四则运算(另外说明下单词都是百度来的...)大致的说明下思路:

加法:

将数字字符串提取出来后从每个数字的最后一位开始相加,用一个变量t来存储是否进位,一开始没有进位所以我给t赋初值为0,每一次我都会判断是否有进位,如果有就让t=1(最多进一位),因为是字符所以运算的时候减去字符‘0’以方便运算。

    while (lena >= 0 && lenb >= 0) {
                        result[i] = a[lena] + b[lenb] - 2 * '0' + t;
                        t = result[i] / 10;
                        result[i] = result[i] % 10 + '0';
                        i++; lena--; lenb--;
                 }

要考虑其中一位加完后另外一位没有加完的情况,这个时候直接将没有加完的加到结果上去就好了

    while (lena >= 0) {//a没加完的情况
        result[i] = a[lena] + t - '0';
        t = result[i] / 10;
        result[i] = result[i] % 10 + '0';
        i++; lena--;
    }
    while (lenb >= 0) {//b没加完的情况
        result[i] = b[lenb] + t - '0';
        t = result[i] / 10;
        result[i] = result[i] % 10 + '0';
        i++; lenb--;
    }
    if (t)result[i++] = t + '0';
    result[i] = '\0';//不要忘了最后加上‘\0’
    BigIntegerResultReverse(result);//同时计算出来的结果其实是倒过来的,再次将结果反转

乘法:

static void BigIntegerMulti(char a[], char b[], char result[])
{
    memset(result, '0', 1000);//先将结果数组初始化一波做准备
    int lena = strlen(a) - 1;
    int lenb = strlen(b) - 1;
    int k = lenb, j = lena, t = 0, temp;//同样的t表示进位
    while (k >= 0) {//数字(组)b的最后一位分别乘以a的每一位
        for (j = lena; j >= 0; j--) {
            temp = (b[k] - '0')*(a[j] - '0') + t + result[lenb - k + lena - j] - '0';//lenb-k表示计算到b的第k位
            result[lenb - k + lena - j] = temp % 10 + '0'; //lena-j表示计算到a的第j位
            t = temp / 10;//lenb - k + lena - j则表示此时正在计算的这一位应该加到结果的第lenb - k + lena - j位上去,想一想你手算的过程
        }

        if (k == 0)break;
        if (t) {
            result[lenb - k + lena + 1] = t + '0';
            t = 0;
        }
        k--;
    }
    if (t) {
        result[lena + lenb + 1] = t + '0';
        result[lena + lenb + 2] = '\0';
    }
    else result[lena + lenb + 1] = '\0';
    BigIntegerResultReverse(result);
}

(本人算法小白,存在的bug还请大佬指点一二),下面给出代码,如果要计算大整数记得在输入的时候加上'L';例如:“L132465454561231+45613465*15341865465”

#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <stdio.h>

static int charactor[256];

static void CharactorInit()
{
	charactor['+'] = 1;
	charactor['-'] = 2;
	charactor['*'] = 3;
	charactor['/'] = 4;
	charactor['('] = 5;
	charactor[')'] = 6;
	//charactor[' '] = 7;
}

static int PriorityJudge(char x1, char x2)
{ //-1:x1<x2  0:x1=x2  1:x1>x2
	if (charactor[x1] >= 1 && charactor[x1] <= 4 && charactor[x2] >= 1 && charactor[x2] <= 4 && x1 == x2)
		return 1;
	if (charactor[x1] == 5)
	{
		if (charactor[x2] == 6)
			return 0;
		return -1;
	}
	if (charactor[x1] == 3 || charactor[x1] == 4)
	{
		if (charactor[x2] == 5)
			return -1;
		return 1;
	}
	if (charactor[x1] == 1 || charactor[x1] == 2)
	{
		if (charactor[x2] <= 5 && charactor[x2] >= 3)
			return -1;
		return 1;
	}
	return -1;
}

// <-------------------------StatementCompulation------------------------------>

#define EMPTY 0
#define StackGrewSpeed 100

typedef struct CompulationStack
{
	int *p = (int *)malloc(sizeof(int) * 1000);
	int *top = p;
	int AllLength = 1000;
	int CurLength = 0;
} CompulationStack;

static int Pop(CompulationStack *stack);
static int Push(CompulationStack *stack, int x);
static int ResizeStack(CompulationStack *stack);
static int IsEmpty(CompulationStack *stack);
static int GetTop(CompulationStack *stack, int *x);
static int Caculator(int a, int b, char method);
static int JudgeCharactor(char x);
static int PriorityJudge(char x1, char x2);

/*
static void InitStatement(int cha) {
	int length = sizeof(cha) / sizeof(int);
	for(int i=0;i<length;i++)cha=
}
*/

static int Pop(CompulationStack *stack)
{
	if (IsEmpty(stack))
		return EMPTY;
	stack->CurLength--;
	return *--stack->top;
}

static int Push(CompulationStack *stack, int x)
{
	if (stack->CurLength >= stack->AllLength)
		ResizeStack(stack);
	*stack->top++ = x;
	stack->CurLength++;
	return 1;
}

static int ResizeStack(CompulationStack *stack)
{
	stack->AllLength += StackGrewSpeed;
	stack->p = (int *)realloc(stack->p, stack->AllLength);
	return 1;
}

static int IsEmpty(CompulationStack *stack)
{
	if (stack->top == stack->p)
		return !EMPTY;
	return EMPTY;
}

static int GetTop(CompulationStack *stack, int *x)
{
	if (!IsEmpty(stack))
	{
		return *x = *(stack->top - 1);
	}
	return 0;
}

static int Caculator(int a, int b, char method)
{
	int a1 = a;
	int a2 = b;
	switch (method)
	{
	case '+':
		return a1 + a2;
	case '-':
		return a1 - a2;
	case '*':
		return a1 * a2;
	case '/':
		return a1 / a2;
	}
	return -1;
}

static int JudgeCharactor(char x)
{
	if (x - '0' >= 0 && x - '0' <= 9)
		return 8;
	return charactor[x];
}

int Compulation(char statement[])
{
	CharactorInit();
	int p, x, result = 0;
	int statementLength = strlen(statement);
	CompulationStack DigitStack;
	CompulationStack CharactorStack;
	for (int i = 0, j; i < statementLength;)
	{
		j = JudgeCharactor(statement[i]);
		if (!j)
			continue;
		if (j == 8)
		{
			int k = i, temp = 0;
			while (JudgeCharactor(statement[i + 1]) == 8)
				i++;
			for (int l = 0; l <= i - k; l++)
				temp += (statement[i - l] - '0') * (int)pow(10, l);
			Push(&DigitStack, temp);
			i++;
		}
		else
		{
			p = PriorityJudge(GetTop(&CharactorStack, &x), statement[i]);
			if (p == 1)
			{
				Push(&DigitStack, Caculator(Pop(&DigitStack), Pop(&DigitStack), Pop(&CharactorStack)));
				//				Push(&CharactorStack, statement[i]);
			}
			else if (p == 0)
			{
				//Push(&DigitStack, Caculator(Pop(&DigitStack), Pop(&DigitStack), Pop(&CharactorStack)));
				Pop(&CharactorStack);
				i++;
			}
			else if (p == -1)
			{
				Push(&CharactorStack, statement[i]);
				i++;
			}
		}
	}
	if (IsEmpty(&CharactorStack))
		return Pop(&DigitStack);
	while (!IsEmpty(&CharactorStack))
		Push(&DigitStack, Caculator(Pop(&DigitStack), Pop(&DigitStack), Pop(&CharactorStack)));
	return Pop(&DigitStack);
	return result;
}

// <------------------------BigInteger------------------------------------------>
#define Max_Biginteger_length 100000
static char result_temp[Max_Biginteger_length];

static void BigIntegerResultReverse(char result[]);

static void BigIntegerAdd(char a[], char b[], char result[]);

static void BigIntegerSub(char a[], char b[], char result[]);

static void BigIntegerMulti(char a[], char b[], char result[]);

//static void BigIntegerdevi(char a[], char b[], char result[]);

typedef struct BigIntegerStack
{
	char *p[5000];
	char **top = p;
	int stackLength = 5000;
	int CurLength = 0;
} BigIntegerStack;

static void B_Pop(BigIntegerStack *big_integer_stack, char p[])
{
	if (big_integer_stack->top == big_integer_stack->p)
	{
		printf("something warning\n");
		exit(0);
	}
	else
		strcpy(p, *--big_integer_stack->top);
	big_integer_stack->CurLength--;
}

static void B_Push(BigIntegerStack *big_integer_stack, char p[])
{
	int len = strlen(p);
	if (*big_integer_stack->top != NULL)free(*big_integer_stack->top);
	*big_integer_stack->top = (char *)malloc(sizeof(char) * (len + 1));
	strcpy(*big_integer_stack->top++, p);
	big_integer_stack->CurLength++;
}

static void BigIntegerResultReverse(char result[])
{
	int start = 0, end = strlen(result) - 1;
	char temp;
	for (; start < end; start++, end--) {
		temp = result[start];
		result[start] = result[end];
		result[end] = temp;
	}//reverse the result array
}

static void BigIntegerAdd(char a[], char b[], char result[])
{
	int lena = strlen(a) - 1;
	int lenb = strlen(b) - 1;
	int t = 0, i = 0;
	while (lena >= 0 && lenb >= 0) {
		result[i] = a[lena] + b[lenb] - 2 * '0' + t;
		t = result[i] / 10;
		result[i] = result[i] % 10 + '0';
		i++; lena--; lenb--;
	}
	while (lena >= 0) {
		result[i] = a[lena] + t - '0';
		t = result[i] / 10;
		result[i] = result[i] % 10 + '0';
		i++; lena--;
	}
	while (lenb >= 0) {
		result[i] = b[lenb] + t - '0';
		t = result[i] / 10;
		result[i] = result[i] % 10 + '0';
		i++; lenb--;
	}
	if (t)result[i++] = t + '0';
	result[i] = '\0';
	BigIntegerResultReverse(result);
}

static void BigIntegerSub(char a[], char b[], char result[])
{
	int lena = strlen(a) - 1;
	int lenb = strlen(b) - 1;
	int t = 0, i = 0, flag = 0;
	if (lena < lenb || (lena == lenb && strcmp(a, b) < 0)) {
		char *p = b; b = a; a = p;
		lena ^= lenb;
		lenb ^= lena;
		lena ^= lenb;
		flag = 1;
	}
	while (lena >= 0 && lenb >= 0) {
		result[i] = a[lena] - b[lenb] + '0' + t;
		if (result[i] < '0') {
			result[i] += 10;
			t = -1;
		}
		else t = 0;
		i++; lena--; lenb--;
	}
	while (lena >= 0) {
		result[i] = a[lena--] + t;
		if (result[i] < '0') {
			result[i] += 10;
			t = -1;
		}
		else t = 0;
		i++;
	}
	if (flag)result[i++] = '-';
	result[i] = '\0';
	BigIntegerResultReverse(result);
}

static void BigIntegerMulti(char a[], char b[], char result[])
{
	memset(result, '0', 1000);
	int lena = strlen(a) - 1;
	int lenb = strlen(b) - 1;
	int k = lenb, j = lena, t = 0, temp;
	while (k >= 0) {
		for (j = lena; j >= 0; j--) {
			temp = (b[k] - '0')*(a[j] - '0') + t + result[lenb - k + lena - j] - '0';
			result[lenb - k + lena - j] = temp % 10 + '0';
			t = temp / 10;
		}
		if (k == 0)break;
		if (t) {
			result[lenb - k + lena + 1] = t + '0';
			t = 0;
		}
		k--;
	}
	if (t) {
		result[lena + lenb + 1] = t + '0';
		result[lena + lenb + 2] = '\0';
	}
	else result[lena + lenb + 1] = '\0';
	BigIntegerResultReverse(result);
}

static char *B_Caculator(char a[], char b[], char method, char result[])//method参数为计算方法(+、-、*),通过对不同计算方法调用不同的大整数运算函数,同时对运算做一些预处理(比如两个负数相加就相当于两个正数相加,最后在所得的结果前面加上负号)
{
	//char result[100000];
	switch (method)
	{
	case '+':
		if (a[0] == b[0] && a[0] == '-') {
			BigIntegerAdd(&a[1], &b[1], result);
			BigIntegerResultReverse(result);
			result[strlen(result) + 1] = '\0';
			result[strlen(result)] = '-';
			BigIntegerResultReverse(result);
		}
		else if (a[0] == '-'&&b[0] != '-')BigIntegerSub(b, &a[1], result);
		else if (b[0] == '-'&&a[0] != '-')BigIntegerSub(a, &b[1], result);
		else BigIntegerAdd(a, b, result);
		break;
	case '-':
		if (a[0] == b[0] && a[0] == '-')
			BigIntegerSub(&b[1], &a[1], result);
		else if (a[0] == '-'&&b[0] != '-') {
			BigIntegerAdd(&a[1], b, result);
			BigIntegerResultReverse(result);
			result[strlen(result) + 1] = '\0';
			result[strlen(result)] = '-';
			BigIntegerResultReverse(result);
		}
		else if (b[0] == '-'&&a[0] != '-')BigIntegerAdd(a, &b[1], result);
		else BigIntegerSub(a, b, result);
		break;
	case '*':
		if (a[0] == b[0] && a[0] == '-')BigIntegerMulti(&a[1], &b[1], result);
		else if (a[0] == '-' || b[0] == '-') {
			if (a[0] == '-')BigIntegerMulti(&a[1], b, result);
			else BigIntegerMulti(a, &b[1], result);
			BigIntegerResultReverse(result);
			result[strlen(result) + 1] = '\0';
			result[strlen(result)] = '-';
			BigIntegerResultReverse(result);
		}
		else BigIntegerMulti(a, b, result);
		break;
	default:
		printf("--> unknown error(maby you input a unkonw charactor\n)");
		break;
	}
	return result;
}

void BigIntegerCompulation(char statement[], char result_buff[])
{
	CharactorInit();
	int p, x, result = 0;
	int statementLength = strlen(statement);
	BigIntegerStack big_integer_stack;
	CompulationStack CharactorStack;
	memset(big_integer_stack.p, NULL, 5000);
	char temp[100000], temp_result[100000];
	for (int i = 0, j; i < statementLength;)
	{
		j = JudgeCharactor(statement[i]);
		if (!j)
			continue;
		if (j == 8)
		{
			int k = i, temp_index = 0;
			while (JudgeCharactor(statement[i]) == 8)//copy the next number
				temp[temp_index++] = statement[i++];
			temp[temp_index] = '\0';
			B_Push(&big_integer_stack, temp);
		}
		else
		{
			p = PriorityJudge(GetTop(&CharactorStack, &x), statement[i]);
			if (p == 1)
			{
				char a[100000], b[100000];
				B_Pop(&big_integer_stack, b);//notice:pop b first,you subtract a subtrahend from a minuend
				B_Pop(&big_integer_stack, a);//a is minuend,b is subtrahend
				B_Push(&big_integer_stack, B_Caculator(a, b, Pop(&CharactorStack), temp_result));
			}
			else if (p == 0)
			{
				//Push(&DigitStack, Caculator(Pop(&DigitStack), Pop(&DigitStack), Pop(&CharactorStack)));
				Pop(&CharactorStack);
				i++;
			}
			else if (p == -1)
			{
				Push(&CharactorStack, statement[i]);
				i++;
			}
		}
	}
	if (IsEmpty(&CharactorStack))
		B_Pop(&big_integer_stack, result_buff);
	else
	{
		while (!IsEmpty(&CharactorStack))
		{
			char a[100000], b[100000];
			B_Pop(&big_integer_stack, b);
			B_Pop(&big_integer_stack, a);
			B_Push(&big_integer_stack, B_Caculator(a, b, Pop(&CharactorStack), temp_result));
		}
		B_Pop(&big_integer_stack, result_buff);
	}
	//BigIntegerResultReverse(result_buff);
	if (result_buff[0] == '0')result_buff[1] = '\0';//if the result is equal to 0
}

int main() {
	char statement[50000], result[2000];
	gets_s(statement);
	if (statement[0] == 'L') {
		BigIntegerCompulation(&statement[1], result);
		printf("%s\n", result);
	}
	else printf("%d\n", Compulation(statement));
	return 0;
}

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值