String Equation解析器问题

时间:2013-03-26 04:11:58

标签: android string math

我正在编写一种解决各种方程的方法。现在我希望该方法接收一个可以采用以下形式的String方程:

ax^2+bx+c=0

*ax^2+c=0*

bx+c=0

等。并且顺序无关紧要。

我的问题是:我如何根据“x”等级解析等式?

eq可以包含更多相同等级的值,例如2x ^ 2 + 4x ^ 2 + 3x + 8 = 2(最大等级x ^ 3)。

如果在double a[]x^2的左侧或右侧,我的方法应将值分配给double b[],如果在左侧或右侧有xdouble c[],如果值附近没有x变量(如果热量位于 = )。

转换double中的字符串数字很简单,但我不知道如何根据所描述的x等级反汇编输入字符串。

2 个答案:

答案 0 :(得分:0)

如果您不受Android限制,我建议使用词法分析器和解析器。这些是代码生成器,因此它们可以在基本语言工作的任何地方工作,但它们往往会产生膨胀的代码。 Android可能不会那么欣赏。

答案 1 :(得分:0)

经过-2x + 3x^2 - 2 + 3x = 3 - 2x^2

的测试
public Double[] parseEquation(String equation)
{
    Log.d(TAG, "equation: " + equation);
    // Remove all white spaces
    equation = equation.replaceAll("[ ]", "");


    // Get the left and right sides of =    
    String[] sides = equation.split("[=]");  // should be of size 2
    boolean leftNegative = false;
    boolean rightNegative = false;
    if (sides.length != 2)
    {
        // There is no = or more than one = signs.
    }
    else
    {
        // if sides i starts with + remove the + 
        // if - we remove and put it back later
        for (int i = 0; i < 2; i++)
        {
            if (sides[i].charAt(0) == '+')
            {
                sides[i] = sides[i].substring(1);
            }
        }

        if (sides[0].charAt(0) == '-')
        {
            leftNegative = true;
            sides[0] = sides[0].substring(1);
        }
        if (sides[1].charAt(0) == '-')
        {
            rightNegative = true;
            sides[1] = sides[1].substring(1);
        }
    }
    Log.d(TAG, "left side:" + sides[0] + " right side: " + sides[1]);

    // Terms without signs need to find out later
    String[] leftTerms = sides[0].split("[+-]");
    String[] rightTerms = sides[1].split("[+-]");

    int length = leftTerms[0].length();
    if (leftNegative)
    {
        leftTerms[0] = "-" + leftTerms[0];
    }
    // put in the minus sign for the rest of the terms

    for (int i = 1; i < leftTerms.length; i++)
    {
        Log.d(TAG, "length = " + length + " " + sides[0].charAt(length));
        if (sides[0].charAt(length) == '-')
        {
            leftTerms[i] = "-" + leftTerms[i];
            length += leftTerms[i].length();
        }
        else
        {
            length += leftTerms[i].length() + 1;
        }   
    }

    length = rightTerms[0].length();
    if (rightNegative)
    {
        rightTerms[0] = "-" + rightTerms[0];
    }

    for (int i = 1; i < rightTerms.length; i++)
    {
        Log.d(TAG, "length = " + length + " " + sides[1].charAt(length));
        if (sides[1].charAt(length) == '-')
        {
            rightTerms[i] = "-" + rightTerms[i];
            length += rightTerms[i].length();
        }
        else
        {
            length += rightTerms[i].length() + 1;
        }   
    }
    //  Now we put all the factors and powers in a list
    List<ContentValues> leftLists = new ArrayList<ContentValues>();

    // left side
    for (int i = 0; i < leftTerms.length; i++)
    {
        Log.d(TAG, "leftTerm: " + leftTerms[i]);
        ContentValues contentValues = new ContentValues();
        int indexOfX = leftTerms[i].indexOf('x');
        if (indexOfX == -1)
        {
            // no x mean a constant term
            contentValues.put("factor", leftTerms[i]);
            contentValues.put("power", "0");
        }
        else
        {
            int indexOfHat = leftTerms[i].indexOf('^');
            if (indexOfHat == -1)
            {
                // no hat mean power = 1
                contentValues.put("power", "1");
                String factor = leftTerms[i].substring(0, indexOfX).trim();
                contentValues.put("factor", factor);
            }
            else
            {
                String power = leftTerms[i].substring(indexOfX + 2).trim();
                String factor = leftTerms[i].substring(0, indexOfX).trim();
                contentValues.put("factor", factor);
                contentValues.put("power", power);
            }
        }
        Log.d(TAG, contentValues.toString());
        leftLists.add(contentValues);
    }

    List<ContentValues> rightLists = new ArrayList<ContentValues>();
    for (int i = 0; i < rightTerms.length; i++)
    {           
        Log.d(TAG, "rightTerm: " + rightTerms[i]);
        ContentValues contentValues = new ContentValues();
        int indexOfX = rightTerms[i].indexOf('x');
        if (indexOfX == -1)
        {
            // no hat mean a constant term
            contentValues.put("factor", rightTerms[i]);
            contentValues.put("power", "0");
        }
        else
        {
            int indexOfHat = rightTerms[i].indexOf('^');
            if (indexOfHat == -1)
            {
                // no hat mean power = 1
                contentValues.put("power", "1");
                String factor = rightTerms[i].substring(0, indexOfX).trim();
                contentValues.put("factor", factor);
            }
            else
            {
                String power = rightTerms[i].substring(indexOfX + 2).trim();
                String factor = rightTerms[i].substring(0, indexOfX).trim();
                contentValues.put("factor", factor);
                contentValues.put("power", power);
            }
        }
        Log.d(TAG, contentValues.toString());
        rightLists.add(contentValues);
    }
    // Now add the factors with same powers.
    // Suppose we solve for cubic here the end result will be 
    // 4 terms constant, x, x^2 and x^3
    // Declare a double array of dim 4 the first will hold constant
    // the second the x factor etc...
    // You can allow arbitrary power by looping through the lists and get the max power
    Double[] result = new Double[]{0.0, 0.0, 0.0, 0.0};
    for (ContentValues c : leftLists)
    {
        switch (c.getAsInteger("power"))
        {
            case 0:
                //Log.d(TAG, "power = 0, factor = " + c.toString());
                result[0] += c.getAsDouble("factor");
                break;

            case 1:
                result[1] += c.getAsDouble("factor");
                break;
            case 2:
                result[2] += c.getAsDouble("factor");
                break;
            case 3:
                result[3] += c.getAsDouble("factor");
                break;
        }
    }

    for (ContentValues c : rightLists)
    {
        switch (c.getAsInteger("power"))
        {
            case 0:
                //Log.d(TAG, "power = 0, factor = " + c.toString());
                result[0] -= c.getAsDouble("factor");
                break;

            case 1:
                result[1] -= c.getAsDouble("factor");
                break;
            case 2:
                result[2] -= c.getAsDouble("factor");
                break;
            case 3:
                result[3] -= c.getAsDouble("factor");
                break;
        }
    }
    Log.d(TAG, "constant term = " + result[0] + ", x^1 = " + result[1]
                 + ", x^2 = " + result[2] + ", x^3 = " + result[3]);
    return result;
}