Java 为什么Apache Commons数学库中的BigFraction类返回不正确的除法结果?

Java 为什么Apache Commons数学库中的BigFraction类返回不正确的除法结果?,java,biginteger,apache-commons-math,Java,Biginteger,Apache Commons Math,本着使用现有、经过测试和稳定的代码库的精神,我开始使用和its为我正在编写的名为RationalAlc的Android应用程序执行一些rational计算 除了一个烦人的问题外,它对我交给它的每一项任务都非常有效。当划分某些bigfract值时,我得到的结果不正确 如果我用除数的倒数创建一个bigfract,然后用乘法代替,我会得到同样的错误答案,但可能这就是库内部正在做的事情 有人知道我做错了什么吗 该除法在大分数为2.5的情况下正常工作,但在2.51、2.49等情况下不正确 [更新] //

本着使用现有、经过测试和稳定的代码库的精神,我开始使用和its为我正在编写的名为RationalAlc的Android应用程序执行一些rational计算

除了一个烦人的问题外,它对我交给它的每一项任务都非常有效。当划分某些
bigfract
值时,我得到的结果不正确

如果我用除数的倒数创建一个
bigfract
,然后用乘法代替,我会得到同样的错误答案,但可能这就是库内部正在做的事情

有人知道我做错了什么吗

该除法在
大分数
为2.5的情况下正常工作,但在2.51、2.49等情况下不正确

[更新]

// *** incorrect! ***
BigFraction one = new BigFraction(1.524);
//one: 1715871458028159 / 1125899906842624

BigFraction two = new BigFraction(2.51);
//two: 1413004383087493 / 562949953421312

BigFraction three = one.divide(two);
//three: 0

Log.i("solve", three.toString());
//should be 0.607171315  ??
//returns 0


// *** correct! ****
BigFraction four = new BigFraction(1.524);
//four: 1715871458028159 / 1125899906842624

BigFraction five = new BigFraction(2.5);
//five: 5 / 2

BigFraction six = four.divide(five);
//six: 1715871458028159 / 2814749767106560

Log.i("solve", six.toString());
//should be 0.6096  ??
//returns 0.6096
这确实是apache commons math 2.0库中的一个bug。该错误在v.2.1中已修复

它现在列在bug tracker的修复问题部分:

感谢@BartK试图重现这个问题,并让我走上了正确的道路

[/UPDATE]

// *** incorrect! ***
BigFraction one = new BigFraction(1.524);
//one: 1715871458028159 / 1125899906842624

BigFraction two = new BigFraction(2.51);
//two: 1413004383087493 / 562949953421312

BigFraction three = one.divide(two);
//three: 0

Log.i("solve", three.toString());
//should be 0.607171315  ??
//returns 0


// *** correct! ****
BigFraction four = new BigFraction(1.524);
//four: 1715871458028159 / 1125899906842624

BigFraction five = new BigFraction(2.5);
//five: 5 / 2

BigFraction six = four.divide(five);
//six: 1715871458028159 / 2814749767106560

Log.i("solve", six.toString());
//should be 0.6096  ??
//returns 0.6096

在构造函数中提供
double
,会导致舍入错误。使用精确的分子和分母将产生预期结果:

public class CommonsMathTest {

    public static void main(String[] args) {

        BigFraction one = new BigFraction(1524, 1000);
        System.out.println("one   = " + one);

        BigFraction two = new BigFraction(251, 100);
        System.out.println("two   = " + two);

        BigFraction three = one.divide(two);
        System.out.println("three = " + three);

        BigFraction four = new BigFraction(1524, 1000);
        System.out.println("four  = " + four);

        BigFraction five = new BigFraction(5, 2);
        System.out.println("five  = " + five);

        BigFraction six = four.divide(five);
        System.out.println("six   = " + six + " = " + six.bigDecimalValue());
    }
}
产生:

one   = 381 / 250
two   = 251 / 100
three = 762 / 1255
four  = 381 / 250
five  = 5 / 2
six   = 381 / 625 = 0.6096
编辑

顺便说一下,我无法复制你的输出。使用Commons Math 2.1,以下内容:

BigFraction one = new BigFraction(1.524);
BigFraction two = new BigFraction(2.51);
BigFraction three = one.divide(two);
System.out.println(three.toString() + " = " +three.doubleValue());
不会像您所说的那样生成
0
,而是打印:

1715871458028159 / 2826008766174986 = 0.6071713147410359

在我看来像个虫子。可能是溢油,因为产品比长条稍大。@starblue快速看了一眼;在内部,
bigfract
似乎使用
biginger
s来存储分子和分母,因此这不是一个简单的方法overflow@starblue,我认为这是一个溢出,但如果是这样的话,BigFraction类抛出异常是否有意义。另外,我选择专门使用BigFraction类,因为它宣传/暗示它没有溢出问题。这让我觉得可能是一只虫子。我要说的是,我是一个相当有经验的程序员,所以我在这里呆了足够长的时间,知道通常是我犯了错误!:)不,它应该正确地使用BigInteger。由于int和long溢出是无声的,所以很难避免错误w.r.t.溢出,在解决Project Euler问题时我已经有过很多次了。在这种情况下,如果你真的想知道你应该调试它,它毕竟是开源的。+1因为这对询问者来说可能是有用的-但尽管如此,在最初的问题中,一旦我们得到了
大分数,除以它们仍然不应该返回零,是吗?@Aakash,没错,我看过了,再看一眼,看看我的编辑。不管我是用double来实例化bigfrance,还是通过提供等效的分子/分母,我都会得到相同的错误。你提到了Commons Math 2.1,但无法重现这个问题引起了我的兴趣,所以我检查了我正在使用的Commons Math jar的版本号。它是2.0——也许这是一个bug,已经修复了。我将升级到2.1,运行单元测试并报告结果。