Java 在有理数的十进制展开中寻找圈

Java 在有理数的十进制展开中寻找圈,java,algorithm,decimal,Java,Algorithm,Decimal,我需要写一个程序,为输入1和33打印0.03。 1/33 = 0.03030303.... 我们使用符号0.03表示03无限重复 再比如,, 8639/70000=0.1234142857 我明白,我需要使用像floyds这样的算法。但是如何在java中获得0.0.030303030303而不是0.03030304。通过使用带向下舍入模式的BigDecimal。通过使用带向下舍入模式的BigDecimal。要正确检测十进制展开中的循环,应该完全避免浮点数学 这里有一种单独使用整数运算的方法:要正

我需要写一个程序,为输入1和33打印0.03。 1/33 = 0.03030303.... 我们使用符号0.03表示03无限重复

再比如,, 8639/70000=0.1234142857


我明白,我需要使用像floyds这样的算法。但是如何在java中获得0.0.030303030303而不是0.03030304。

通过使用带向下舍入模式的BigDecimal。

通过使用带向下舍入模式的BigDecimal。

要正确检测十进制展开中的循环,应该完全避免浮点数学


这里有一种单独使用整数运算的方法:

要正确检测十进制展开中的周期,您应该完全避免使用浮点运算


这里有一种单独使用整数运算的方法:

通过这段代码,我想您会找到您想要的:

BigDecimal one = new BigDecimal(1);

BigDecimal thirtyThree = new BigDecimal(33);

//Fix the decimals you want, i.e. 21
MathContext context = new MathContext(21, RoundingMode.DOWN);

BigDecimal result = one.divide(thirtyThree, context);       

System.out.println(result);
这将产生下一个结果:
0.0303030303030303

有了这个代码,我想你会找到你想要的:

BigDecimal one = new BigDecimal(1);

BigDecimal thirtyThree = new BigDecimal(33);

//Fix the decimals you want, i.e. 21
MathContext context = new MathContext(21, RoundingMode.DOWN);

BigDecimal result = one.divide(thirtyThree, context);       

System.out.println(result);
这将产生下一个结果:
0.0303030303

您可以尝试以下更健壮的方法

理论上,所有重复序列都必须是

1/9 or 0.(1), 
1/99 or 0.(01)
1/999 or 0.(001)
1/9999 or 0.(0001)
etc.
所以要找出一个分数是9,99,999,9999等的因子,一旦你知道你的分母是哪个9的因子,你就知道它是如何重复的

/*
8639/70000 : 0.1234(142857)
1/1: 1.
1/2: 0.5
1/3: 0.(3)
1/4: 0.25
1/5: 0.2
1/6: 0.1(6)
1/7: 0.(142857)
1/8: 0.125
1/9: 0.(1)
1/10: 0.1
1/11: 0.(09)
1/12: 0.08(3)
1/13: 0.(076923)
1/14: 0.0(714285)
 etc
 */
public static final BigInteger NINE = BigInteger.valueOf(9);

public static void main(String... args) {
    System.out.println("8639/70000 : " + repeatingFraction(8639, 70000));
    for (int i = 1; ; i++)
        System.out.println("1/" + i + ": " + repeatingFraction(1, i));
}

private static String repeatingFraction(long num, long den) {
    StringBuilder sb = new StringBuilder();
    sb.append(num / den);
    sb.append('.');
    num %= den;
    for (int i = 3, lim = (int) Math.sqrt(num); i <= lim; i++) {
        while (num % i == 0 && den % i == 0) {
            num /= i;
            den /= i;
        }
    }

    while (num > 0) {
        while (den % 2 == 0 && num % 2 == 0) {
            num /= 2;
            den /= 2;
        }
        while (den % 5 == 0 && num % 5 == 0) {
            num /= 5;
            den /= 5;
        }
        // simplify.
        BigInteger nine = NINE;
        BigInteger denBI = BigInteger.valueOf(den);
        long lim = den;
        while (lim % 2 == 0) lim /= 2;
        while (lim % 5 == 0) lim /= 5;
        for (int j = 1; j <= lim; j++, nine = nine.multiply(BigInteger.TEN).add(NINE)) {
            if (nine.mod(denBI).equals(BigInteger.ZERO)) {
                BigInteger repeat = BigInteger.valueOf(num).multiply(nine).divide(denBI);
                sb.append('(').append(String.format("%0" + j + "d", repeat)).append(')');
                return sb.toString();
            }
        }
        num *= 10;
        sb.append(num / den);
        num %= den;
    }
    return sb.toString();
}

您可以尝试以下更健壮的方法

理论上,所有重复序列都必须是

1/9 or 0.(1), 
1/99 or 0.(01)
1/999 or 0.(001)
1/9999 or 0.(0001)
etc.
所以要找出一个分数是9,99,999,9999等的因子,一旦你知道你的分母是哪个9的因子,你就知道它是如何重复的

/*
8639/70000 : 0.1234(142857)
1/1: 1.
1/2: 0.5
1/3: 0.(3)
1/4: 0.25
1/5: 0.2
1/6: 0.1(6)
1/7: 0.(142857)
1/8: 0.125
1/9: 0.(1)
1/10: 0.1
1/11: 0.(09)
1/12: 0.08(3)
1/13: 0.(076923)
1/14: 0.0(714285)
 etc
 */
public static final BigInteger NINE = BigInteger.valueOf(9);

public static void main(String... args) {
    System.out.println("8639/70000 : " + repeatingFraction(8639, 70000));
    for (int i = 1; ; i++)
        System.out.println("1/" + i + ": " + repeatingFraction(1, i));
}

private static String repeatingFraction(long num, long den) {
    StringBuilder sb = new StringBuilder();
    sb.append(num / den);
    sb.append('.');
    num %= den;
    for (int i = 3, lim = (int) Math.sqrt(num); i <= lim; i++) {
        while (num % i == 0 && den % i == 0) {
            num /= i;
            den /= i;
        }
    }

    while (num > 0) {
        while (den % 2 == 0 && num % 2 == 0) {
            num /= 2;
            den /= 2;
        }
        while (den % 5 == 0 && num % 5 == 0) {
            num /= 5;
            den /= 5;
        }
        // simplify.
        BigInteger nine = NINE;
        BigInteger denBI = BigInteger.valueOf(den);
        long lim = den;
        while (lim % 2 == 0) lim /= 2;
        while (lim % 5 == 0) lim /= 5;
        for (int j = 1; j <= lim; j++, nine = nine.multiply(BigInteger.TEN).add(NINE)) {
            if (nine.mod(denBI).equals(BigInteger.ZERO)) {
                BigInteger repeat = BigInteger.valueOf(num).multiply(nine).divide(denBI);
                sb.append('(').append(String.format("%0" + j + "d", repeat)).append(')');
                return sb.toString();
            }
        }
        num *= 10;
        sb.append(num / den);
        num %= den;
    }
    return sb.toString();
}

对于任意精度,您需要使用BigDecimal。为了获得更高的精度,您应该使用分数。您需要求值,直到得到9,99,999,9999的倍数…对于任意精度,您需要使用BigDecimal。为了获得更高的精度,您应该使用分数。您需要求值,直到得到9,99,999,9999的倍数…这是隐式的0.03030303030000000000000000000;当然,你不能存储一个无限的数字,你必须根据你使用的上下文选择正确的小数。另一种选择是将所有的数字都保留为分数,这样就不会丢失精度。您需要的位数迅速增加。1/97=0.0103092788350515463917525773195876288659793814432989690721649484536082474226804123711340206185567这意味着0.03030303030330000000000000000000;当然,你不能存储一个无限的数字,你必须根据你使用的上下文选择正确的小数。另一种选择是将所有的数字都保留为分数,这样就不会丢失精度。您需要的位数迅速增加。1/97=0.01030927883505154639717525773195876288659793814432989690721649484536082474226804123711340206185567您在这里使用的算法是什么?我自己编的;我确定它有个名字,但我不知道它是什么。你在这里使用的算法是什么?我自己编的;我肯定它有名字,但我不知道它是什么。