waterml/src/main/java/ucar/nc2/ogc/erddap/util/ErddapString2.java
public static int[] toRational(double d) {        
        if (d == 0)
            return new int[]{0, 0};

        if (!ErddapMath2.isFinite(d))
            return new int[]{1, Integer.MAX_VALUE};

        String s = "" + d; //-12.0 or 6.6260755E-24
        //String2.log("\nd=" + d + "\ns=" + s);
        int ten = 0;

        //remove the e
        int epo = s.indexOf('E');
        if (epo > 0) {
            ten = parseInt(s.substring(epo + 1));
            s = s.substring(0, epo);
            //String2.log("remove E s=" + s + " ten=" + ten);
        }

        //remove .0; remove decimal point
        if (s.endsWith(".0"))
            s = s.substring(0, s.length() - 2);
        int dpo = s.indexOf('.');
        if (dpo > 0) {
            ten -= s.length() - dpo - 1;
            s = s.substring(0, dpo) + s.substring(dpo + 1);
            //String2.log("remove . s=" + s + " ten=" + ten);
        }

        //convert s to long
        //need to lose some precision?
        long tl = parseLong(s);    
        //String2.log("tl=" + tl + " s=" + s);
        while (Math.abs(tl) > 1000000000) {
            tl = Math.round(tl / 10.0);
            ten++;
            //String2.log("tl=" + tl + " ten=" + ten);
        }
        //remove trailing 0's
        while (tl != 0 && tl / 10 == tl / 10.0) {
            tl /= 10;
            ten++;
            //String2.log("remove 0 tl=" + tl + " ten=" + ten);
        }
        //add up to 3 0's?
        if (tl < 100000 && ten >= 1 && ten <= 3) {
            while (ten > 0) {
                tl *= 10;
                ten--;
            }
        }

        return new int[]{(int)tl, ten}; //safe since large values handled above
    }
public static int[] toRational(double d) {        
        if (d == 0)
            return new int[]{0, 0};

        if (!ErddapMath2.isFinite(d))
            return new int[]{1, Integer.MAX_VALUE};

        String s = "" + d; //-12.0 or 6.6260755E-24
        //String2.log("\nd=" + d + "\ns=" + s);
        int ten = 0;

        //remove the e
        int epo = s.indexOf('E');
        if (epo > 0) {
            ten = parseInt(s.substring(epo + 1));
            s = s.substring(0, epo);
            //String2.log("remove E s=" + s + " ten=" + ten);
        }

        //remove .0; remove decimal point
        if (s.endsWith(".0"))
            s = s.substring(0, s.length() - 2);
        int dpo = s.indexOf('.');
        if (dpo > 0) {
            ten -= s.length() - dpo - 1;
            s = s.substring(0, dpo) + s.substring(dpo + 1);
            //String2.log("remove . s=" + s + " ten=" + ten);
        }

        //convert s to long
        //need to lose some precision?
        long tl = parseLong(s);    
        //String2.log("tl=" + tl + " s=" + s);
        while (Math.abs(tl) > 1000000000) {
            tl = Math.round(tl / 10.0);
            ten++;
            //String2.log("tl=" + tl + " ten=" + ten);
        }
        //remove trailing 0's
        while (tl != 0 && tl / 10 == tl / 10.0) {
            tl /= 10;
            ten++;
            //String2.log("remove 0 tl=" + tl + " ten=" + ten);
        }
        //add up to 3 0's?
        if (tl < 100000 && ten >= 1 && ten <= 3) {
            while (ten > 0) {
                tl *= 10;
                ten--;
            }
        }

        return new int[]{(int)tl, ten}; //safe since large values handled above
    }
This converts a double to a rational number (m * 10^t).
This is similar to Math2.mantissa and Math2.intExponent, but works via string manipulation
to avoid roundoff problems (e.g., with 6.6260755e-24).

@param d
@return int[2]: [0]=m, [1]=t.
(or {0, 0} if d=0, or {1, Integer.MAX_VALUE} if !finite(d))