0

I am making a calculator app and it basically builds a string that uses rhino to process an equation . But the problem is that I can't find a way to handle percentage . It does not accepts % symbol.

I need to replace all instances of it with "?/100*?" inside the string where the ?st is the number preceding the percentage and ?nd number used with percentage .

example "5 + 3% + 2" --> "5 + 5/100*3 + 2" .

The issue is I can't know what kind of number could be expected , it could even be something like (5+4)-(3+1)% or a long decimal. Since the percentage is inside a string I do not use variables . Here is the example below (method that is invoked when equals button is pressed) :

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("");
    });

I am using this helper library : https://github.com/F43nd1r/rhino-android

I do not have experience in working with rhino so I do not know if there is a simple solution . I think that the only solution would be to build a complex string parsing method that will check what precedes the percentage and to reformat it . Is there any other way regarding rhino ?

Here is a string formatting method I wrote . It can properly handle any equation that contains a single % :

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;
}

The problem with the method above is that it is still missing support to detect and handle brackets like (5+4)-(4+2)% . Which I can write . But it makes errors when there are two % present . For instance : 5+10%-4+50% will become 5+ 5/10010 - 4 + 4/10050 . The above equation will end up producing bad results for some reason . What would be necessary is inclusion of brackets etc .. I just hoped that there was an easier way .

1 Answers1

0

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 %.

triplej
  • 269
  • 4
  • 9
  • 1
    "/100" results in bad calculation for percentage . Proper : 5 + 10% = 5 + 0,5 (as 10% of 5) . What happens : 5 + 10% = 5 + 10 (as 10% of 100) . It always calculates percentage of number 100 rather then the number it is supposed to . Proper calculation would be : 5 + 10% = 5 + 5/100*10 (which is 5 + 0.5) . It's just quite complex to make a string formatting method that will account for brackets and multiple occurrences of % like 5+3% - 4+7% . I already have code that forbids all invalid inputs like ++ +/ %% etc . And ?/100*? was just an example where ? meant where missing digits go . – Grim Reaper May 02 '21 at 01:31
  • I revised my answer based on this clarification. – triplej May 02 '21 at 05:58
  • 1
    @triplej Does Nashorn support Android? You may just wish to link to [How to execute JavaScript on Android?](https://stackoverflow.com/q/8374016/295004) for alternate JS engine recommendations. – Morrison Chang May 02 '21 at 09:18