为什么求幂(例如 10^6)比 R 中的计算器符号(例如 1e6)长 4 倍?

Why does exponentiation (e.g., 10^6) take 4 times longer than calculator notation (e.g., 1e6) in R?

在 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 的时间与计算 exp{6*log(10)} 的时间大致相同?我理解 R 在计算 10^6 时执行一个函数,但为什么要这样编码?

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

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

这是因为 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"