检查双倍是否= 1/3

MCM*_*ery 6 java math

我已经创建了一个函数,它将doubleJava 转换为简化的部分:

public static int gcm(int a, int b) {
    return b == 0 ? a : gcm(b, a % b);
}
public static String toFraction(double d) {
    int decimals = String.valueOf(d).split("\\.")[1].length();
    int mult = (int) Math.pow(10, decimals);
    int numerator = (int) (d * mult);
    int denominator = mult;
    // now simplify
    int gcm = gcm(numerator, denominator);
    numerator /= gcm;
    denominator /= gcm;
    return numerator + "/" + denominator;
}
Run Code Online (Sandbox Code Playgroud)

它有效,除了我使用的事实toFraction(1.0/3),这将是可以理解的回归"715827882/2147483647".我怎么能解决这个问题"1/3"呢?

Pet*_*rey 6

您必须允许某个错误,并且并非所有分数都可以精确地表示为标量值.

public static String toFraction(double d, double err) {
    String s = Long.toString((long) d);
    d -= (long) d;
    if (d > err) {
        for (int den = 2, max = (int) (1 / err); den < max; den++) {
            long num = Math.round(d * den);
            double d2 = (double) num / den;
            if (Math.abs(d - d2) <= err)
                return (s.equals("0") ? "" : s + " ") + num +"/"+den;
        }
    }
    return s;
}

public static void main(String... args) {
    System.out.println(toFraction(1.0/3, 1e-6));
    System.out.println(toFraction(1.23456789, 1e-6));
    System.out.println(toFraction(Math.E, 1e-6));
    System.out.println(toFraction(Math.PI, 1e-6));
    for (double d = 10; d < 1e15; d *= 10)
        System.out.println(toFraction(Math.PI, 1.0 / d));
}
Run Code Online (Sandbox Code Playgroud)

版画

1/3
1 19/81
2 719/1001
3 16/113
3 1/5
3 1/7
3 9/64
3 15/106
3 16/113
3 16/113
3 3423/24175
3 4543/32085
3 4687/33102
3 14093/99532
3 37576/265381
3 192583/1360120
3 244252/1725033
3 2635103/18610450
Run Code Online (Sandbox Code Playgroud)

注意:这可以找到PI的21/7,333/106和355/113近似值.