首页 > 解决方案 > 如何用犀牛脚本处理百分比?

问题描述

我正在制作一个计算器应用程序,它基本上构建了一个使用 rhino 来处理方程的字符串。但问题是我找不到处理百分比的方法。它不接受 % 符号。

我需要用“?/ 100 *?”替换它的所有实例 在字符串中,其中 ?st 是百分比之前的数字,而 ?nd 与 percent 一起使用。

例如 "5 + 3% + 2" --> "5 + 5/100*3 + 2" 。

问题是我不知道可以预期什么样的数字,它甚至可能是 (5+4)-(3+1)% 或长小数。由于百分比在字符串中,因此我不使用变量。这是下面的示例(按下等于按钮时调用的方法):

btnEquals.setOnClickListener(v -> {
        
        process = tvInput.getText().toString();
        process = process.replaceAll("%", "?/100*?"); // this is the problem line

        rhinoAndroidHelper = new RhinoAndroidHelper(this);
        context = rhinoAndroidHelper.enterContext();

        context.setOptimizationLevel(-1);
        String finalResult = "";

        try {
            Scriptable scriptable = context.initStandardObjects();
            finalResult = context.evaluateString(scriptable, process, "javascript", 1, null).toString();
        } catch (Exception e) {
            finalResult = "0";
        }

        tvOutput.setText(finalResult);
        tvInput.setText("");
    });

我正在使用这个助手库:https ://github.com/F43nd1r/rhino-android

我没有使用犀牛的经验,所以我不知道是否有一个简单的解决方案。我认为唯一的解决方案是构建一个复杂的字符串解析方法,该方法将检查百分比之前的内容并重新格式化它。关于犀牛还有其他方法吗?

这是我写的一个字符串格式化方法。它可以正确处理任何包含单个 % 的方程:

private void format(String s){
    int newIndex = s.indexOf("%");
    int nextIndex = newIndex;


    StringBuilder percentage = new StringBuilder();
    StringBuilder value = new StringBuilder();
    char character;

    String result = "";
    StringBuilder newProcess = new StringBuilder(s);

    boolean done = true;
    boolean firstPartDone = false;
    boolean firstSymbol = false;

    while(done){
        while (!firstPartDone){
            if(nextIndex == 0){
                done = false;
            }

            nextIndex--;
            character = s.charAt(nextIndex);
            if(character == '+' | character == '/' | character == '*' | character == '-'){
                firstPartDone = true;
            }else{
                percentage.insert(0, character);
            }
        }
        if(nextIndex == 0){
            done = false;
        }
        character = s.charAt(nextIndex);
        if(character == '+' | character == '/' | character == '*' | character == '-'){
            if(!firstSymbol){
                // value.insert(0, character);
                nextIndex--;
                firstSymbol = true;
            }else{
                done = false;
            }

        }else{
            value.insert(0, character);
            nextIndex--;
        }
    }


    // percentage.append("%");
    System.out.println(percentage);
    System.out.println(value);

    result = value + "/100*" + percentage;
    String percent = percentage.toString();
    String percentToReplace = percent.concat("%");
    String finalString = newProcess.toString();
    finalString = finalString.replace(percentToReplace, result);

    process = finalString;
}

上述方法的问题在于它仍然缺少检测和处理括号的支持,例如 (5+4)-(4+2)% 。我可以写。但是当有 2% 存在时它会出错。例如: 5+10%-4+50% 将变为 5+ 5/100 10 - 4 + 4/100 50 。由于某种原因,上述等式最终会产生不好的结果。有必要包含括号等。我只是希望有一种更简单的方法。

标签: javaandroidcalculatorpercentagerhino

解决方案


Rhino is a javascript engine without DOM support. If vanilla javascript can do it, Rhino can do it.

Since the meaning of % is context dependent, I don't think there's any easy way to use Rhino (vanilla javascript) to solve it. You need to parse it or find a library that will parse it. You can use javascript libraries with Rhino https://groups.google.com/g/mozilla.dev.tech.js-engine.rhino/c/fS8KQelY0bs

FYI - Baleudung says Rhino is obsolete and Nashorn is faster.

Original response:

Try using process = process.replaceAll("%", "/100");

replaceAll accepts a regex and every time the regex is found it replaces it with exactly the replacement value. In your first example it will be changed it to 5+3?/100*?+2, which is not valid javascript

/ has priority over + so it will adjust the values to percentages before adding the numbers.

Depending on how you want the calculator to work, this may have issues when multiple % are used. For example, 5+3%% or (1-3)+(1+2%)%. You need to decide if you want 3%% to mean 3/100/100 or not. If you want to reject %%, you could handle this in the input stage, by not letting %% be entered or after the input stage by parsing it to turn %% into %.


推荐阅读