Converting a float into a string fraction representation

后端 未结 6 767
一整个雨季
一整个雨季 2021-01-17 20:23

In Java, I am trying to find a way to convert a float number into a fraction string. For example:

float num = 1.33333;
String numStr = Convert(num); // Shoul         


        
相关标签:
6条回答
  • 2021-01-17 20:32

    Assume you have "0.1234567", then count how many numbers after the decimal point (which is 7). then multiply the number with 10 ^ 7, now you have "1234567".

    divide 1234567 over 10 ^ 7. Then, simplify the fraction using the GCD of the two numbers.

    0.1234567 * 10000000 = 1234567
    => 1234567 / 10000000
    => System.out.println(1234567 / gcd(1234567,10000000) + "/" + 10000000/gcd(1234567,10000000));
    
    0 讨论(0)
  • 2021-01-17 20:34

    Look into chain fractions. This allows you to determine denominator and fraction within a given accuracy.

    For Pi you can get 22/7 or 355/113 depending on when you choose to stop.

    0 讨论(0)
  • 2021-01-17 20:34

    Modified the FOR loop to break the loop, when the best denominator is already identified.

    if (error2 == 0) break;

    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));
        }
    }
    
    0 讨论(0)
  • 2021-01-17 20:39

    The simplest approach might be to use trial and error.

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

    prints

    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
    
    0 讨论(0)
  • 2021-01-17 20:39

    This might be of help:

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

    Otherwise you'd need some way of telling Convert() how far out you want to take things. Maybe a maximum reduced demoninator or something like that. That way you'll get "1 1/3" for both of the first two examples you have above rather than "1 33333/100000" for the first and "1 333/1000" for the second.

    0 讨论(0)
  • 2021-01-17 20:50

    Extract the fractional part of the number (for example, ((int) 0.5 + 1) - 0.5, then divide one by the result (1 / 0.5). You'll get the denominator of the fraction. Then cast the float to an int, and you'll get the integer part. Then concatenate both.

    It's just a simple solution, and will work only if the numerator of the fraction is 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
    
    0 讨论(0)
提交回复
热议问题