【问题标题】:Why Ruby and Python long division differs from GMP and Java BigInteger?为什么 Ruby 和 Python 长除法不同于 GMP 和 Java BigInteger?
【发布时间】:2013-08-28 04:32:34
【问题描述】:

我正在开发一个 Big Integer 类(教学目的),我一直在使用 Ruby 来生成测试用例。我的课程在以下测试中失败:

a = -48197174570431531987668852939807674377435188974148779416366905274642031729688518691
b = 4322669160730708444058642850762359547515258361061655693150034467061
a / b = -11149864303351921    # Ruby answer

我在我的代码中找不到错误,所以我尝试使用其他工具验证结果并感到惊讶:o。

GMP、Java BigInteger 和我的类结果不谋而合:

11149864303351920
-11149864303351920

但 Ruby 和 Python 恰逢此:

-11149864303351921
11149864303351920

有人能解释一下为什么会出现这种行为吗?请。

【问题讨论】:

  • 我想你是在问为什么 Python 和 Ruby 中的否定结果少一个。在 Python 中,整数除法层,here is why.
  • @StevenRumbalski,是的,这就是我要找的。​​span>

标签: java python ruby gmp bignum


【解决方案1】:

当整数除法的参数不都是正数时,必须决定对商和余数的符号进行四舍五入。 GMP 支持地板除法 (f_div...)、天花板除法 (c_div...) 和截断除法 (t_div...)。

使用gmpy2通过Python访问GMP,

>>> import gmpy2
>>> a = -48197174570431531987668852939807674377435188974148779416366905274642031729688518691
>>> b = 4322669160730708444058642850762359547515258361061655693150034467061
>>> gmpy2.f_divmod(a,b)
(mpz(-11149864303351921), mpz(1542354793066875276328139562907995977816446564586050094773477055490))
>>> gmpy2.c_divmod(a,b)
(mpz(-11149864303351920), mpz(-2780314367663833167730503287854363569698811796475605598376557411571))
>>> gmpy2.t_divmod(a,b)
(mpz(-11149864303351920), mpz(-2780314367663833167730503287854363569698811796475605598376557411571))
>>> help(gmpy2.f_divmod)
f_divmod(x, y) -> (quotient, remainder)

Return the quotient and remainder of x divided by y. The quotient
is rounded towards -Inf (floor rounding) and the remainder will
have the same sign as y. x and y must be integers.

>>> help(gmpy2.c_divmod)
c_divmod(x, y) -> (quotient, remainder)

Return the quotient and remainder of x divided by y. The quotient
is rounded towards +Inf (ceiling rounding) and the remainder will
have the opposite sign of y. x and y must be integers.

>>> help(gmpy2.t_divmod)
t_divmod(x, y) -> (quotient, remainder)

Return the quotient and remainder of x divided by y. The quotient
is rounded towards zero (truncation) and the remainder will have
the same sign as x. x and y must be integers.

【讨论】:

    【解决方案2】:

    问题在于整数除法。 python 2.x(我假设是ruby,虽然我不是那里的专家)默认情况下进行整数除法。如果你在 python 中这样做:

    from __future__ import division
    
    a = -48197174570431531987668852939807674377435188974148779416366905274642031729688518691
    b = 4322669160730708444058642850762359547515258361061655693150034467061
    
    print int(a/b)
    

    你会看到你期待的答案。

    请注意,此行为在 python 3+ 中是默认行为,from __future__ 导入仅在 python 2.2+ 中可用。

    这里有更多信息。关于整数除法,由Wikipedia 提供 :)

    编辑:

    正如 Steve Rumbalski 所指出的,显着的区别在于舍入的方式。 Python 的整数除法向负无穷大舍入,而不是向零舍入(这样 -0.2 变为 -1)。正如我在上面所做的那样,强制浮点(“真”)除法然后在最后转换为int,这意味着舍入的方式不同,这就是为什么我上面的示例得到“正确”答案的原因。

    【讨论】:

    • -1。看起来他不是在寻找浮点答案。如果这是真的,那么你的答案是错误的。
    • @StevenRumbalski -- 我认为 OP 一方面在寻找 GMP、Java 和他自己的类之间差异的解释,另一方面是他的 Python 和 Ruby 测试。正如我所指出的,正确的答案是:Python 和 Ruby 示例使用整数除法。对不对?
    • 看看他给出的结果。他对整数结果很好。如果你看java的BigInteger,除法的结果是另一个BigInteger。
    • @StevenRumbalski -- 我现在明白你的意思了,你说得很对。我已经更新了我的答案。
    • 仍然不正确。 Python 3 的整数除法与 Python 2 相同,只是拼写不同(// vs /)。
    猜你喜欢
    • 2016-04-17
    • 2010-09-06
    • 2015-11-29
    • 1970-01-01
    • 2013-08-30
    • 2018-05-03
    • 1970-01-01
    • 2012-08-05
    • 2014-10-11
    相关资源
    最近更新 更多