R中的For-loop vs while循环

Ale*_*lex 25 floating-point for-loop r while-loop

我在R中工作的时候注意到了一个奇怪的事情.当我有一个简单的程序来计算从1到N的平方时使用for-loop和while循环实现的行为是不一样的.(在这种情况下我不关心矢量化或应用函数).

fn1 <- function (N) 
{
    for(i in 1:N) {
        y <- i*i
    }
}
Run Code Online (Sandbox Code Playgroud)

fn2 <- function (N) 
{
    i=1
    while(i <= N) {
        y <- i*i
        i <- i + 1
    }
}
Run Code Online (Sandbox Code Playgroud)

结果是:

system.time(fn1(60000))
   user  system elapsed 
  2.500   0.012   2.493 
There were 50 or more warnings (use warnings() to see the first 50)
Warning messages:
1: In i * i : NAs produced by integer overflow
.
.
.

system.time(fn2(60000))
   user  system elapsed 
  0.138   0.000   0.137 
Run Code Online (Sandbox Code Playgroud)

现在我们知道for循环更快,我的猜测是因为预分配和优化.但它为什么会溢出?

更新:所以现在尝试使用矢量的另一种方式:

fn3 <- function (N) 
{
    i <- 1:N
    y <- i*i
}
system.time(fn3(60000))
   user  system elapsed 
  0.008   0.000   0.009 
Warning message:
In i * i : NAs produced by integer overflow
Run Code Online (Sandbox Code Playgroud)

那也许它是一个时髦的记忆问题?我在OS X上运行4G内存和R中的所有默认设置.这种情况发生在32位和64位版本中(除了时间更快).

亚历克斯

Ale*_*own 37

因为1是数字,但不是整数(即它是浮点数),并且1:6000是数字和整数.

> print(class(1))
[1] "numeric"
> print(class(1:60000))
[1] "integer"
Run Code Online (Sandbox Code Playgroud)

60000平方是36亿,这在带符号的32位整数中是不可表示的,因此会出现溢出错误:

> as.integer(60000)*as.integer(60000)
[1] NA
Warning message:
In as.integer(60000) * as.integer(60000) : NAs produced by integer overflow
Run Code Online (Sandbox Code Playgroud)

但是,浮点数很容易代表36亿:

> as.single(60000)*as.single(60000)
[1] 3.6e+09
Run Code Online (Sandbox Code Playgroud)

要修复for代码,请转换为浮点表示:

function (N)
{
    for(i in as.single(1:N)) {
        y <- i*i
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这就是为什么seq(N)优先于1:N? (2认同)