大整数的有底除法和欧几里得除法

Posted

技术标签:

【中文标题】大整数的有底除法和欧几里得除法【英文标题】:Floored and Euclidean division of big integers 【发布时间】:2015-03-22 12:48:04 【问题描述】:

Java 的 BigInteger 类提供截断除法(商和余数)。以此为出发点,实现底除法和欧几里得除法(商和余数)最简单、最有效的方法是什么?

【问题讨论】:

你到底追求什么?为什么不使用 BigDecimal? 澄清一下,您希望结果向负无穷大而不是向零舍入? @SMA 我正在用算术实现一阶逻辑的 TPTP 规范,它规定了所有三种整数除法。 BigDecimal 解决了另一个问题,除非我遗漏了什么? @OliverCharlesworth 是的,如***.com/questions/4102423/… 看看Guava的BigIntegerMath.divide 【参考方案1】:

根据Soronbe 的回答,以下是正确Java 语法的实现(不包括地板除法的第二个变体):

public BigInteger euclidianDivision(BigInteger a, BigInteger b) 
    return
        a.subtract(
            a.compareTo(BigInteger.ZERO) < 0 ?
                b.subtract(BigInteger.ONE) :
                    BigInteger.ZERO
        ).divide(b)


public BigInteger flooredDivision(BigInteger a, BigInteger b) 
    return
        a.add(
            (a.compareTo(BigInteger.ZERO) < 0) != (b.compareTo(BigInteger.ZERO) < 0) ?
                b.subtract(BigInteger.ONE) :
                    BigInteger.ZERO
        ).divide(b);

更新: 对于根据三种除法计算余数,其中两个已经在BigInteger 中实现(mod 用于欧几里德除法,remainder 用于截断除法)。要获得地板除法的余数,可以使用以下实现:

public BigInteger flooredRemainder(BigInteger a, BigInteger b) 
    return
        a.mod(b).subtract(
            b.compareTo(BigInteger.ZERO) < 0 ? BigInteger.ONE : BigInteger.ZERO
        );

【讨论】:

【参考方案2】:

根据:https://***.com/a/4110620/4701236,这应该是相当有效的。请注意,这是在 C 而不是 Java 中测试效率的,但看到差异相当小,我不希望它们在 Java 中很大(实现之间的差异,而不是 C 和 Java 之间的差异),因为当前的 Java 编译器优化了很多。

public BigInteger euclidianDivision(BigInteger a,BigInteger b)
    return (a - (a<0 ? b-1 : 0)).divide(b)


public BigInteger flooredDivision(BigInteger a,BigInteger b)
    return (a + ( ((x<0) != (y<0))? b-1 : 0)).divide(b)


public BigInteger secondFlooredDivision(BigInteger a,BigInteger b)
    return (a + ( ((a ^ b) < 0)? b-1 : 0)).divide(b)

secondFlooredDivision 对负数的二进制表示做了假设,所以我建议你使用另一个。目前无法测试此代码,所以如果有人可以运行它并纠正可能的语法错误(我将其编写为伪代码)。

【讨论】:

以上是关于大整数的有底除法和欧几里得除法的主要内容,如果未能解决你的问题,请参考以下文章

欧几里得算法(辗转相除法)计算最大公约数

欧几里得算法(辗转相除法)

辗转相除法求最大公约数c语言代码

欧几里得算法

约数(试除法求约数,约数之和,约数之差,欧几里得算法)

浅谈关于欧几里得的一系列算法