求解数组中的方程

时间:2009-10-02 01:03:43

标签: c++ arrays

我试图找出如何解决已存储在数组中的方程式。 我需要一些关于如何克服这种问题的指导。 这是我的条件

  • 我有一个数组int X [30];
  • 并且在那里我存储了我想要的等式:5 + 6 * 20/4
  • 同样,我无法存储操作数(+ / - *)所以我使用了不同的标识符,如(-1 -2 -3 -4),因为方程中不应该有负值。

任何帮助将不胜感激

感谢

7 个答案:

答案 0 :(得分:8)

如果要在C中完成,那么我建议使用prefixpostfix评估技巧。有一些技术可以将给定的中缀表达式转换为前缀或后缀表示法。您可以详细了解这些符号及其转换here

使用这些,您的等式(5+6*20/4)将转换为以下前缀表示法:

+ 5 * 6 / 20 4

前缀=运算符出现在任何操作数之前 Infix =运算符在操作数之间 Postfix =运算符在两个操作数之后

当它存储在两个堆栈,数字和操作中时,这就是你得到的:

int nums[] = {4, 20, 6, 5);
char opers[] = {'/', '*', '+'}

请注意订单的逆转。

您现在可以使用简单的push pop技术和优先级来评估它:

  1. 从操作员堆栈中弹出操作员
  2. 从操作数堆栈弹出两个操作数并将操作应用于它们
  3. 将结果推回堆栈
  4. 继续上述操作,直到在操作数堆栈上留下一个结果(并且操作符堆栈为空)

    上述试运行:

    Iteration 1: 
    

    '/'应用于4和20给5,将其推回操作数堆栈。

    nums = {5, 6, 5};
    opers = {'*', '+'};
    

    -

    Iteration 2:
    

    '*'应用于5和6,给予30,将其推回操作数堆栈

    nums = {30, 5};
    opers = {'+'};
    

    -

    Iteration 3:
    

    '+'应用于30和5,给出35,将其推回操作数堆栈

    现在,操作符堆栈为空,操作数堆栈有一个值:35,这是你的答案。

答案 1 :(得分:4)

这听起来像是一种表达方程式的不太理想的方式。您是否需要遵守正确的数学运算符优先级?换句话说,6 * 20/4优先于5 + 6?

解决它的有效方法是使用flex和bison等工具从语言语法创建代码。但是如果这是一个小的家庭作业而不是生产代码那么你可以通过从左到右扫描一起破解一些东西......跳过+ - 操作和评估* /操作到位(确保你向下移动其余的数组元素) )。在减少了所有* /操作后,您可以评估+ - 操作。

Step 0: 5+6*20/4
Step 1: 5+120/4
Step 2: 5+30
Step 3: 35

答案 2 :(得分:3)

通常,您必须定义每个操作的优先级并逐个处理它们。


First your expression is:        '`[ 5,-1, 6,-4,20,-2, 4]`'
Do all '/' first:                '`[ 5,-1, 6,-4, 5,-1, 0]`' <- 20/ 4 =  5+0
Then, do all '*':                '`[ 5,-1,30,-1, 0,-1, 0]`' <-  6* 5 = 30+0
Then, do all '-':                '`[ 5,-1,30,-1, 0,-1, 0]`' <-  Nothing
Then, do all '+' (sum positive): '`[35,-1, 0,-1, 0,-1, 0]`' <-  5+30+0+0 = 35 + 0 + 0

ADDED:这是C代码。

void ShowArray(int pX[], int pLength) {
    int i;
    for(i = 0; i < pLength; i++)
        printf("%3d ", pX[i]);
    printf("\n");
}
 
void ShiftArray(int pX[], int pIndex, int pSkip, int pLength) {
    int i;
    for(i = pIndex; i < (pLength - pSkip); i++)
        pX[i] = pX[i + pSkip];
 
    for(i = (pLength - pSkip); i < pLength; i++)
        pX[i] = 0;
}
 
int main(void) {
    const int OPERCOUNT =  4;
    const int PLUS      = -1;  // -1 Do last
    const int SUBT      = -2;
    const int MULT      = -3;
    const int DIV       = -4;  // -4 Do first
 
    int X[]    = {5, PLUS, 6, MULT, 20, DIV, 4};
    int XCount = 7;
 
    ShowArray(X, XCount);
 
    int i;
    for(i = OPERCOUNT; --i >= 0; ) {
        int OPER = -(i + 1);

        int j = 0;
        for(j = 0; j < XCount; j++) {
            int x = X[j];
            if (x == OPER) {
                if      (x == PLUS) X[j - 1] = X[j - 1] + X[j + 1];
                else if (x == SUBT) X[j - 1] = X[j - 1] - X[j + 1];
                else if (x == MULT) X[j - 1] = X[j - 1] * X[j + 1];
                else if (x == DIV ) X[j - 1] = X[j - 1] / X[j + 1];
                ShiftArray(X, j, 2, XCount);
            }
        }
 
        ShowArray(X, XCount);
    }
 
    int Sum = 0;
    int j;
    for(j = 0; j < XCount; j++) {
        int x = X[j];
        if (x > 0) Sum += x;
    }
    printf("Result: %d\n", Sum);
}

结果如下:

  5  -1   6  -3  20  -4   4 
  5  -1   6  -3   5   0   0 
  5  -1  30   0   0   0   0 
  5  -1  30   0   0   0   0 
 35   0   0   0   0   0   0 
Result: 35

这应该有效。

享受编码。

答案 3 :(得分:2)

这是我快速提出的内容。不是我最干净的代码(几乎没有发布)但它尊重操作的顺序,可以处理数字变为负数。

#include <stdio.h>

int main(int argc, char** argv){
    int e[] = {5,-1,6,-2,20,-4,4,-3,50,-1,100,-5};
    int l;

    printf("\n\n");
    int* cpi = e;
    while(*cpi != -5 ){
        if(*cpi == -1)
            printf(" +");
        else if(*cpi == -2)
            printf(" *");
        else if(*cpi == -3)
            printf(" -");
        else if(*cpi == -4)
            printf(" /");
        else
            printf(" %d",*cpi);
        *cpi = *cpi >= 0 ? *cpi + 1 : *cpi;
        cpi++;
    }
    printf("\n\n");

    int op1 = -2;
    int op2 = -4;


    int loop = 0;
    for(loop = 0 ; loop < 2 ; loop++){  
        cpi = e;
        while(*cpi != -5 ){
            if(*cpi == op1 || *cpi == op2){
                int* p1 = cpi-1;
                int* p2 = cpi+1;

                while(*p1 <= 0 && *p1 >= -5)
                    p1--;

                while(*p2 <= 0 && *p2 >= -5)
                    p2++;

                int v1 = *p1 > 0 ? *p1 - 1 : *p1 + 5;
                int v2 = *p2 > 0 ? *p2 - 1 : *p2 + 5;

                int r;

                if(*cpi == -2){
                    r = v1 * v2;
                    printf("%d * %d = %d\n",v1,v2,r);
                }
                else if(*cpi == -4){
                    r = v1 / v2;
                    printf("%d / %d = %d\n",v1,v2,r);
                }
                else if(*cpi == -1){
                    r = v1 + v2;
                    printf("%d + %d = %d\n",v1,v2,r);
                }
                else if(*cpi == -3){
                    r = v1 - v2;
                    printf("%d - %d = %d\n",v1,v2,r);
                }
                r = r >= 0 ? r + 1 : r - 5;

                *cpi = r;
                *p1 = 0;
                *p2 = 0;
            }
            cpi++;
        }
        op1 = -1;
        op2 = -3;
    }


    cpi = e;
    while(*cpi <= 0 && *cpi >= -5){
        cpi++;
    }
    int r = *cpi;
    r = r > 0 ? r - 1 : r + 5;
    printf("Result: %d\n",r);

    return 0;
}

输出:

5 + 6 * 20/4 - 50 + 100

6 * 20 = 120

120/4 = 30

5 + 30 = 35

35 - 50 = -15

-15 + 100 = 85

结果:85

答案 4 :(得分:0)

正如您所发现的,int数组对于等式是一个糟糕的抽象。

C ++是一种面向对象的语言。开始考虑对象,并尝试抽象出方程的一些特征。

您需要更像this的内容。

答案 5 :(得分:0)

您可以按顺序存储操作符后面的值。由于操作员始终会遵循一个值,因此您不必担心使用底片进行计算,或将它们混合起来。

对于运算符(+ / - *),您可以直接将其存储为ASCII字符,因为字符是一个字节整数。然后运营商将转换为(+ / - *) - &gt; (43 47 45 42) 例如,上面的等式看起来像:

  • array [0] - &gt; 5
  • array [1] - &gt; 43
  • array [2] - &gt; 6
  • array [3] - &gt; 42
  • array [4] - &gt; 20
  • array [5] - &gt; 47
  • array [6] - &gt; 4

可选:您可以添加一个特殊字符来表示等式的结束

  • array [7] - &gt;你的选择

如果空间或性能令人担忧,你可以使事情复杂化,但我认为在这种情况下它没问题。

答案 6 :(得分:0)

正如其他人所指出的那样,将一个方程存储到一个整数数组中并不是世界上最好的事情。假设这不是一个需要你使用数组的家庭作业,我建议你开发自己的类,它可以更强大地处理方程。

至于你当前的数组方法,我会把它改成std :: vector。然后我想我会按照这些方式实现一些东西:

Go through the array until we find the operator with greatest precedence
Once we've found it, apply the operator and store the result in place of one of the numbers. Remove the operator and the unused number operated on from the vector
Keep going until the whole vector has had that particular operator applied
Go back to the beginning, but do this for the next-highest precedence operator