10

Java では、浮動小数点数を小数文字列に変換する方法を見つけようとしています。例えば:

float num = 1.33333;
String numStr = Convert(num); // Should return "1 1/3"

float num2 = 1.333;
String numStr2 = Convert(num2); // Should also return "1 1/3"

float num3 = 0.5;
String numStr3 = Convert(num3); // Should return "1/2"

float num4 = 2.25;
String numStr4 = Convert(num4); // Should return "2 1/4"

Javaでこれを行う方法はありますか?

4

6 に答える 6

11

最も単純なアプローチは、試行錯誤を使用することです。

public static String toFraction(double d, int factor) {
    StringBuilder sb = new StringBuilder();
    if (d < 0) {
        sb.append('-');
        d = -d;
    }
    long l = (long) d;
    if (l != 0) sb.append(l);
    d -= l;
    double error = Math.abs(d);
    int bestDenominator = 1;
    for(int i=2;i<=factor;i++) {
        double error2 = Math.abs(d - (double) Math.round(d * i) / i);
        if (error2 < error) {
            error = error2;
            bestDenominator = i;
        }
    }
    if (bestDenominator > 1)
        sb.append(' ').append(Math.round(d * bestDenominator)).append('/') .append(bestDenominator);
    return sb.toString();
}

public static void main(String... args)  {
    System.out.println(toFraction(1.3333, 1000));
    System.out.println(toFraction(1.1428, 1000));
    for(int i=1;i<100000000;i*=10) {
        System.out.println("PI "+i+": "+toFraction(3.1415926535897932385, i));
    }
}

版画

1 1/3
1 1/7
PI 1: 3
PI 10: 3 1/7
PI 100: 3 14/99
PI 1000: 3 16/113
PI 10000: 3 16/113
PI 100000: 3 14093/99532
PI 1000000: 3 140914/995207
PI 10000000: 3 244252/1725033
于 2011-05-11T18:33:38.900 に答える
1

連鎖分数を調べます。これにより、特定の精度内で分母と分数を決定できます。

Pi の場合、いつ停止するかによって、22/7 または 355/113 を取得できます。

于 2011-05-11T18:23:48.037 に答える
0

「0.1234567」があると仮定して、小数点以下の数値(7)を数えます。次に、数値に10 ^ 7を掛けると、「1234567」になります。

1234567を10^7で割ります。次に、2つの数値のGCDを使用して分数を単純化します。

0.1234567 * 10000000 = 1234567
=> 1234567 / 10000000
=> System.out.println(1234567 / gcd(1234567,10000000) + "/" + 10000000/gcd(1234567,10000000));
于 2011-05-11T18:37:46.847 に答える
0

これは役立つかもしれません:

http://www.merriampark.com/fractions.htm

それ以外の場合は、 Convert() にどれだけ遠くまで移動したいかを伝える何らかの方法が必要になります。たぶん、最大の削減された悪魔か何か。そうすれば、最初の例が「1 33333/100000」、2 番目が「1 333/1000」ではなく、上記の最初の 2 つの例の両方で「1 1/3」が得られます。

于 2011-05-11T18:14:54.207 に答える
0

数値の小数部分を抽出します (たとえば、((int) 0.5 + 1) - 0.5その後、結果 ( ) で 1 を割り1 / 0.5ます)。分数の分母を取得します。次に、float を int にキャストすると、整数部分が取得されます。次に連結します。両方。

これは単純な解決策であり、分数の分子が 1 の場合にのみ機能します。

double n = 1.2f;

int denominator = 1 / (Math.abs(n - (int) n - 0.0001)); //- 0.0001 so the division doesn't get affected by the float point aproximated representation
int units = (int) n;

int numerator = units * denominator + 1;

System.out.println("" + numerator + "/" + denominator); //6/5
System.out.println("" + units + " 1/" + denominator); //1 1/5
于 2011-05-11T18:14:58.467 に答える
0

最適な分母が既に特定されている場合、ループを中断するように FOR ループを変更しました。

if (error2 == 0) ブレーク;

public static String toFraction(double d, int factor) {
    StringBuilder sb = new StringBuilder();
    if (d < 0) {
        sb.append('-');
        d = -d;
    }
    long l = (long) d;
    if (l != 0) sb.append(l);
    d -= l;
    double error = Math.abs(d);
    int bestDenominator = 1;
    for(int i=2;i<=factor;i++) {
        double error2 = Math.abs(d - (double) Math.round(d * i) / i);
        if (error2 < error) {
            error = error2;
            bestDenominator = i;
            if (error2 == 0) break;
        }
    }
    if (bestDenominator > 1)
        sb.append(' ').append(Math.round(d * bestDenominator)).append('/') .append(bestDenominator);
    return sb.toString();
}

public static void main(String... args)  {
    System.out.println(toFraction(1.3333, 1000));
    System.out.println(toFraction(1.1428, 1000));
    for(int i=1;i<100000000;i*=10) {
        System.out.println("PI "+i+": "+toFraction(3.1415926535897932385, i));
    }
}
于 2013-08-27T02:02:29.553 に答える