Long story short, I'm working in a system that only works with groovy in its expression editor, and I need to create a function that returns the number of significant figures an integer has. I've found the following function in stack overflow for Java, however it doesnt seem like groovy (or the system itself) likes the regex:

String myfloat = "0.0120";

String [] sig_figs = myfloat.split("(^0+(\\.?)0*|(~\\.)0+$|\\.)");

int sum = 0;

for (String fig : sig_figs)
{
    sum += fig.length();
}

return sum;

I've since tried to convert it into a more Groovy-esque syntax to be compatible, and have produced the following:

def sum = 0;

def myint = toString(mynum);

def String[] sig_figs = myint.split(/[^0+(\\.?)0*|(~\\.)0+$|\\.]/);

for (int i = 0; i <= sig_figs.size();i++)
{
    sum += sig_figs[i].length();
}
return(sum); 

Note that 'mynum' is the parameter of the method

It should also be noted that this system has very little visibility in regards to what groovy functions are available in the system, so the solution likely needs to be as basic as possible

Any help would be greatly appreciated. Thanks!

2

There are 2 best solutions below

0
tim_yates On BEST ANSWER

I think this is the regex you need:

def num = '0.0120'
def splitted = num.split(/(^0+(\.?)0*|(~\.)0+$|\.)/)
def sf = splitted*.length().sum()
3
Wasabi Thumbs On

It's been a while since I've had to think about significant figures, so sorry if I have the wrong idea. But I've made two regular expressions that combined should count the number of significant figures (sorry I'm no regex wizard) in a string representing a decimal. It doesn't handle commas, you would have to strip those out.

This first regex matches all significant figures before the decimal point

([1-9]+\d*[1-9]|[1-9]+)

And this second regex matches all significant figures after the decimal point:

\.((\d*[1-9]+)+)?

If you add up the lengths of the first capture group (or 0 when no match) for both matches, then it should give you the number of significant figures.

Example:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SigFigs {

    private static final Pattern pattern1 = Pattern.compile("([1-9]+\\d*[1-9]|[1-9]+)");
    private static final Pattern pattern2 = Pattern.compile("\\.((\\d*[1-9]+)+)?");

    public static int getSignificantFigures(String number) {
        int sigFigs = 0;
        for (int i=0; i < 2; i++) {
            Matcher matcher = (i == 0 ? pattern1 : pattern2).matcher(number);
            if (matcher.find()) {
                try {
                    String s = matcher.group(1);
                    if (s != null) sigFigs += s.length();
                } catch (IndexOutOfBoundsException ignored) { }
            }
        }
        return sigFigs;
    }
    
    public static void main(String[] args) {
        System.out.println(getSignificantFigures("0305.44090")); // 7 sig. figs
    }

}

Of course using two matches is suboptimal (like I've said, I'm not crazy good at regex like some I could mention) but its fairly robust and readable