【问题标题】:How to process percentage with rhino script?如何用犀牛脚本处理百分比?
【发布时间】:2021-07-24 20:09:34
【问题描述】:

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

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

示例 "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/10010 - 4 + 4/10050 。 由于某种原因,上述等式最终会产生不好的结果。需要的是包含括号等.. 我只是希望有更简单的方法。

【问题讨论】:

    标签: java android calculator percentage rhino


    【解决方案1】:

    Rhino 是一个不支持 DOM 的 javascript 引擎。如果 vanilla javascript 能做到,Rhino 也能做到。

    由于 % 的含义取决于上下文,我认为没有任何简单的方法可以使用 Rhino (vanilla javascript) 来解决它。您需要解析它或找到一个可以解析它的库。你可以使用 javascript 库和 Rhino https://groups.google.com/g/mozilla.dev.tech.js-engine.rhino/c/fS8KQelY0bs

    仅供参考 - Baleudung says Rhino is obsolete and Nashorn is faster.

    原始回复:

    尝试使用process = process.replaceAll("%", "/100");

    replaceAll 接受一个正则表达式,每次找到正则表达式时,它都会用替换值替换它。在您的第一个示例中,它将更改为 5+3?/100*?+2,这不是有效的 javascript

    / 的优先级高于 +,因此它会在添加数字之前将值调整为百分比。

    根据您希望计算器的工作方式,使用多个 % 时可能会出现问题。例如,5+3%% 或 (1-3)+(1+2%)%。您需要决定是否要 3%% 表示 3/100/100。如果你想拒绝 %%,你可以在输入阶段处理这个问题,不让 %% 被输入,或者在输入阶段之后通过解析将 %% 转换为 %。

    【讨论】:

    • "/100" 导致百分比计算错误。正确:5 + 10% = 5 + 0,5(作为 5 的 10%)。会发生什么:5 + 10% = 5 + 10(作为 100 的 10%)。它总是计算数字 100 的百分比,而不是它应该计算的数字。正确的计算是:5 + 10% = 5 + 5/100*10(即 5 + 0.5)。制作一个字符串格式化方法非常复杂,该方法将考虑括号和 % 的多次出现,例如 5+3% - 4+7% 。我已经有禁止所有无效输入的代码,例如 ++ +/ %% 等。还有 ?/100*?只是一个例子在哪里?意味着丢失的数字去哪里。
    • 我根据这个澄清修改了我的答案。
    • @triplej Nashorn 支持 Android 吗?您可能只想链接到 How to execute JavaScript on Android? 以获取其他 JS 引擎建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-02
    • 1970-01-01
    • 2011-02-15
    • 2010-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多