为什么求幂(例如 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^6
和 12^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"
在 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^6
和 12^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"