R

时间:2017-03-15 13:39:00

标签: r multiplication modular-arithmetic

我有一个大约1000个元素的向量,从大约1到10,我希望所有元素的乘积乘以模10 ^ 6。即,我想要类似于

的东西
x <- as.integer(runif(1000, 1, 10))
prod(x) %% 1000000

但是,由于prod(x)评估为Inf,因此上述内容只会返回NaN

在我的实际应用中(这并不是最小的,所以我不会把它放在这里),我已经用for循环完成了这个,比如

x <- as.integer(runif(1000, 1, 10))

for (i in 1:length(x)) {
  if (i == 1) {
    y <- x[i]
  } else {
    y <- y * x[i]
    y <- y %% 1000000
  }
}
y

最初我只是想寻求一个比for循环更好的解决方案的帮助,假设我应该在R中避免这个。但是,在写这个问题时,我现在同样感到困惑的是事实上,我似乎无法为for循环生成有效的MWE。上面的代码返回0,但是当我删除as.integer()时它可以正常工作。我花了比我更长的时间来承认试图弄清楚为什么会这样,但是我很难过。

然后有两个问题:

  • 为什么上述MWE不起作用? (为什么没有as.integer呢?)
  • 什么是在R中实现模块化乘法的好方法,可以避免溢出问题?理想情况下,我对基础R中的解决方案感到好奇,即没有类似gmp包的东西。我已尝试使用sapply / lapply,但到目前为止无济于事。

我发现了其他语言提出的类似问题,但我很难解读这些术语中的答案,我很害怕。

1 个答案:

答案 0 :(得分:0)

让我们看看会发生什么:

set.seed(42)
x <- as.integer(runif(1000, 1, 10))

y <- integer(1000)
for (i in 1:length(x)) {
  if (i == 1) {
    y[i] <- x[i]
  } else {
    y[i] <- y[i-1] * x[i]
    y[i] <- y[i] %% 1000000
  }
}
y[1:30]
# [1]      9     81    243   1944  11664  58320 408240 816480 898880 292160 460800 225600  30400  91200 456000 104000 936000
#[18] 872000 360000 160000 440000 880000 920000 280000 280000 400000 600000 400000      0      0

好的,所以问题出现在第29次迭代中:

400000 * x[29]
#[1] 2e+06

为什么浮点数不会发生?

set.seed(42)
x <- (runif(1000, 1, 10))

y <- integer(1000)
for (i in 1:length(x)) {
  if (i == 1) {
    y[i] <- x[i]
  } else {
    y[i] <- y[i-1] * x[i]
    y[i] <- y[i] %% 1000000
  }
}
y[1:30]
 #[1] 9.233254e+00 8.710356e+01 3.114175e+02 2.638961e+03 1.788083e+04 1.014176e+05 7.737451e+05 7.115236e+05 9.187133e+05
#[10] 7.484847e+05 8.319994e+05 2.167078e+05 3.966498e+04 1.308492e+05 6.752649e+05 3.880944e+05 8.048925e+05 6.559748e+05
#[19] 4.602498e+05 7.812873e+05 1.380611e+05 3.104154e+05 7.312040e+04 6.961072e+05 2.125757e+05 1.963559e+05 8.859247e+05
#[28] 1.076669e+05 5.407815e+05 6.096419e+05

如你所见,你永远不会得到1e6的倍数。

请注意,由于您在每次迭代中计算模数,因此您的循环与向量化尝试不同。

您可以考虑使用任意精度数作为替代(参见包Rmpfr)。或者使用更智能的算法。