如何从大的小数中恢复初始分数

How to restore initial fraction from a big decimal

我有一个分数列表,必须先将其转换为 bigDecimal,然后再次转换为分数。我做了两种方法:首先从分数转换为 bigDecimal,第二种则相反。但是,我注意到在转换过程中我失去了一些精度,因此我想知道是否有办法以 100% 的信心将分数恢复到其初始状态,假设我可以存储任意数量的小数。

这是我的代码,在打印件上,您会注意到我在非常小的分数上失去了精度。

package Docs;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.math3.fraction.BigFraction;

public class FractionalApproximation{

    private static BigDecimal fractionToPercentage(String fraction) {
        final String[] split = fraction.split("/");
        final float numerator = Float.valueOf(split[0]);
        final float denominator = Float.valueOf(split[1]);
        return new BigDecimal((numerator / denominator) * 100).setScale(3, BigDecimal.ROUND_HALF_DOWN);
    }


    private static String percentageToFraction(double share){
        double percentage = share / 100;
        BigFraction bigFraction = new BigFraction(percentage, 0.002D, 1000);
        return bigFraction.getNumerator() + "/" + bigFraction.getDenominator();
    }


    public static void main(String[] args) {
        List<String> initialFractions = new ArrayList<String>(Arrays.asList("1/3","1/112","1/6","1/1","1/56","1/224", "1/448", "4/448"));
        System.out.println(initialFractions);

        List<BigDecimal> percentageResultList = new ArrayList<BigDecimal>();
        for(String fraction : initialFractions){
            percentageResultList.add(fractionToPercentage(fraction));
        }
        System.out.println(percentageResultList);


        List<String> fractionResultList = new ArrayList<String>();
        for(BigDecimal value : percentageResultList){
            fractionResultList.add(percentageToFraction(value.doubleValue()));
        }
        System.out.println(fractionResultList);
    }
}



 Initial fractions :[1/3, 1/112, 1/6, 1/1, 1/56, 1/224, 1/448, 4/448]
 Fractions converted to BigDecimal: [33.333, 0.893, 16.667, 100.000, 1.786, 0.446, 0.223, 0.893]
 BigDecimal converted to fraction:  [1/3, 1/111, 1/6, 1/1, 1/55, 1/224, 1/448, 1/111]

我建议您研究连分数,尤其是阅读 https://en.wikipedia.org/wiki/Continued_fraction#Best_rational_approximations。该部分描述了如何使用计算连分数来更准确地表示给定的实数。

你还有两个问题需要处理。

一个是您将需要选择要继续多长时间,即您认为这些值中的哪些实际上贡献了应该表示的细节,而哪些只是来自计算的噪音。如果你的大小数没有数字噪音,即整数除法的直接和正确四舍五入的结果,那么你可以用相同的数字计算每个收敛的小数表示,看看它们中的哪一个与你的完全匹配输入。

另一个问题是,计算连分数需要进行大量运算,这些运算在使用大小数执行时会带来自身的舍入误差。特别是您将需要计算多个反转,即将 x 映射到 1/x。如果在第一步中将大小数转换为某种形式的大有理数(即两个大整数的商),然后在那里执行所有步骤,您可能会过得更好。初始转换和所有后续转换都应该在大有理表示中是准确的。