python-3.x R中大数之间模运算的错误结果

hgb9j2n6  于 2022-12-20  发布在  Python
关注(0)|答案(1)|浏览(86)

为了解决hackerrank中的一个难题,我尝试在R中的大数之间应用模运算(v4.2.2)。但是,当至少有一个操作数非常大时,我会得到不正确的结果。例如,52504222585724001 %% 10在R中生成0。这是不正确的。但是,当我在python(v3.9.12)中尝试52504222585724001 % 10时,我得到了正确的结果1。所以我决定测试一些其他的数字。我下载了一组测试用例,我的代码失败了,我对每个n值都做了n*n mod (10^9 + 7)

R代码:

summingSeries <- function(n) {
  return(n^2 %% (10^9 + 7))
}

n <- c(229137999, 344936985, 681519110, 494844394, 767088309, 307062702, 306074554, 555026606, 4762607, 231677104)
expected <- c( 218194447, 788019571, 43914042, 559130432, 685508198, 299528290, 950527499, 211497519, 425277675, 142106856 )

result <- rep(0L, length(n))

start <- Sys.time()
for (i in 1:length(n)){
  result[i] <- summingSeries(n[i])
}
print(Sys.time() - start)
df <- data.frame(expected, result, diff = abs(expected - result))
print(df)

我在下面粘贴结果和与预期值的绝对差异

expected    result   diff
-------------------------
218194447 218194446    1
788019571 788019570    1
43914042  43914070    28
559130432 559130428    4
685508198 685508205    7
299528290 299528286    4
950527499 950527495    4
211497519 211497515    4
425277675 425277675    0
142106856 142106856    0

Python 3代码:

import numpy as np

def summingSeries(n):
    return(n ** 2 % (10 ** 9 + 7))

n = [229137999,
    344936985,
    681519110,
    494844394,
    767088309,
    307062702,
    306074554,
    555026606,
    4762607,
    231677104]

expected = [218194447,
    788019571,
    43914042,
    559130432,
    685508198,
    299528290,
    950527499,
    211497519,
    425277675,
    142106856]

result = [0] * len(n)
for i in range(0, len(n)):
  result[i] = summingSeries(n[i])

print(np.array(result) -  np.array(expected))

我用上面的python代码得到了正确的结果。有人能解释一下为什么会有不一致的地方,为什么R会产生错误的结果吗?

k10s72fa

k10s72fa1#

使用gmp包(参见Carl Witthoft的评论)。

gmp::mod.bigz(gmp::as.bigz(n)^2, 1e9 + 7) - expected
#> Big Integer ('bigz') object of length 10:
#>  [1] 0 0 0 0 0 0 0 0 0 0

先前/较差答案:

library(Rmpfr)

n <- c(229137999, 344936985, 681519110, 494844394, 767088309, 307062702, 306074554, 555026606, 4762607, 231677104)
expected <- c(218194447, 788019571, 43914042, 559130432, 685508198, 299528290, 950527499, 211497519, 425277675, 142106856)
data.frame(
  precision = 53:64, # 53 corresponds to double precision
  sumAbsErr = sapply(53:64, function(p) sum(abs(expected - as.numeric(mpfr(n, p)^2 %% (1e9 + 7)))))
)
#>    precision sumAbsErr
#> 1         53        53
#> 2         54        29
#> 3         55        21
#> 4         56        16
#> 5         57         1
#> 6         58         1
#> 7         59         1
#> 8         60         0
#> 9         61         0
#> 10        62         0
#> 11        63         0
#> 12        64         0

60位的精度对于这个例子来说已经足够了。

相关问题