为什么Ruby和Python长分区不同于GMP和Java BigInteger?

时间:2013-08-28 04:32:34

标签: java python ruby gmp bignum

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

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

我无法在代码中找到错误,因此我尝试使用其他工具验证结果并感到惊讶:o。

GMP,Java BigInteger和我的课程恰好符合这一结果:

11149864303351920
-11149864303351920

但Ruby和Python恰逢其后:

-11149864303351921
11149864303351920

有人可以解释一下这种行为的原因吗?请。

2 个答案:

答案 0 :(得分:1)

问题在于整数除法。 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,正如我上面所做的那样,意味着舍入以不同方式完成,这就是为什么我上面的例子得到“正确”的答案。 / p>

答案 1 :(得分: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.