为啥求幂(例如 10^6)比 R 中的计算器符号(例如 1e6)花费的时间长 4 倍?

Posted

技术标签:

【中文标题】为啥求幂(例如 10^6)比 R 中的计算器符号(例如 1e6)花费的时间长 4 倍?【英文标题】:Why does exponentiation (e.g., 10^6) take 4 times longer than calculator notation (e.g., 1e6) in R?为什么求幂(例如 10^6)比 R 中的计算器符号(例如 1e6)花费的时间长 4 倍? 【发布时间】:2015-07-12 07:34:56 【问题描述】:

在 R 代码中使用科学记数法 10^6(我通常这样做)会导致比使用计算器表示 1e6 更长的计算时间:

> system.time(for (t in 1:1e7) x=10^6) 
  utilisateur     système      écoulé 
        4.792       0.000       4.281 
> system.time(for (t in 1:1e7) x=1e6) 
 utilisateur     système      écoulé 
       0.804       0.000       1.051
> system.time(for (t in 1:1e7) x=exp(6*log(10)))
 utilisateur     système      écoulé 
       6.301       0.000       5.702

为什么 R 重新计算 10^6 的时间与计算 exp6*log(10) 的时间差不多?我理解R在计算10^6时会执行一个函数,但是为什么要这样编码呢?

【问题讨论】:

我猜一个是只需要翻译的数字文字,而另一个是首先需要评估的表达式。 你为什么认为R通过exp(6*log(10))计算10^6 这不是您所说的“以特定方式编码”的问题,而是您明确告诉 R 计算 10 的 6 次方...例如,您宁愿分配 @ C++ 中的 987654329@ 或 double a=pow(10,6); @cryo111:我理解原因,但对使用幂符号时的效率损失感到遗憾。这不是世界末日,但我在未来的代码中必须小心这一点。 @Xi'an BTW 一个好问题。此外,您还得到了两个不错的答案以及 MrFlick 和 Josh 的一些有趣的额外见解。 +1 全部 【参考方案1】:

这是因为1e6 是constant,并且被解析器识别为这样,而10^6 被解析为必须进一步评估的函数调用(通过调用函数^()) .由于前者避免了函数调用的昂贵开销,因此评估它要快得多!

class(substitute(1e6))
# [1] "numeric"
class(substitute(10^6))
# [1] "call"

为了更好地看出这是一个电话,你可以这样剖析它:

as.list(substitute(10^6))
# [[1]]
# `^`
# 
# [[2]]
# [1] 10
# 
# [[3]]
# [1] 6

其他一些有趣的案例:

## negative numbers are actually parsed as function calls
class(substitute(-1))
[1] "call"

## when you want an integer, 'L' notation lets you avoid a function call 
class(substitute(1000000L))
# [1] "integer"
class(substitute(as.integer(1000000)))
# [1] "call"

【讨论】:

非常有趣的附加案例!但令人费解。我以前从未听说过使用 L(但分配负数时似乎并没有节省时间) @Xi'an 是的,R 使用尾随 L 来指示整数与将 - 视为函数调用不同。据我所知,如果不执行函数调用,根本无法提供负常数 --- 没有 "1N" 等。【参考方案2】:

1e6 的情况下,您指定的是文字数值。那里没有进行计算。

当您请求10^6 时,R 会执行将 10 提高到 6 次方的工作。 ^ 是一个数字运算符。它对 base 10 没有任何特殊作用。它不知道 10^612^14 之间的区别。它必须进行计算才能找到答案。

【讨论】:

谢谢。遗憾的是,10 没有获得特殊地位! 赋予 10 个特殊状态会使解析器复杂化。我显然没有做任何测试,但这很可能会比偶尔的功率计算更慢。

以上是关于为啥求幂(例如 10^6)比 R 中的计算器符号(例如 1e6)花费的时间长 4 倍?的主要内容,如果未能解决你的问题,请参考以下文章

使用求幂**0.5 比 math.sqrt 效率低?

计算 p^q(求幂)的有效方法,其中 q 是整数

为啥我无法解析符号“R”? [复制]

R:计算和解释逻辑回归中的优势比

矩阵求幂,用于计算可能的路线数量

如何在 Bash 中求幂