variable - naming in a loop r
For-loop vs while loop en R (3)
He notado algo curioso mientras trabajaba en R. Cuando tengo un programa simple que calcula cuadrados de 1 a N implementados usando for-loop y while-loop el comportamiento no es el mismo. (No me importa la vectorización en este caso o aplicar funciones).
fn1 <- function (N)
{
for(i in 1:N) {
y <- i*i
}
}
Y
fn2 <- function (N)
{
i=1
while(i <= N) {
y <- i*i
i <- i + 1
}
}
Los resultados son:
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
Ahora sabemos que for-loop es más rápido, mi suposición es debido a la asignación previa y optimizaciones allí. Pero, ¿por qué se desborda?
ACTUALIZACIÓN: Entonces, ahora probando de otra manera con vectores:
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
Entonces tal vez es un problema de memoria funky? Me estoy ejecutando en OS X con 4 GB de memoria y todos los ajustes predeterminados en R. Esto sucede en las versiones de 32 y 64 bits (excepto que los tiempos son más rápidos).
Alex
La variable en el bucle for es una secuencia entera, y finalmente haces esto:
> y=as.integer(60000)*as.integer(60000)
Warning message:
In as.integer(60000) * as.integer(60000) : NAs produced by integer overflow
mientras que en el ciclo while estás creando un número de punto flotante.
También es la razón por la cual estas cosas son diferentes:
> seq(0,2,1)
[1] 0 1 2
> seq(0,2)
[1] 0 1 2
No me creas?
> identical(seq(0,2),seq(0,2,1))
[1] FALSE
porque:
> is.integer(seq(0,2))
[1] TRUE
> is.integer(seq(0,2,1))
[1] FALSE
Porque 1
es numérico, pero no entero (es decir, es un número de coma flotante), y 1:6000
es numérico y entero.
> print(class(1))
[1] "numeric"
> print(class(1:60000))
[1] "integer"
60000 al cuadrado es 3.6 mil millones, que NO es representable en un entero de 32 bits con signo, por lo tanto obtienes un error de desbordamiento:
> as.integer(60000)*as.integer(60000)
[1] NA
Warning message:
In as.integer(60000) * as.integer(60000) : NAs produced by integer overflow
3.6 billones es fácilmente representable en coma flotante, sin embargo:
> as.single(60000)*as.single(60000)
[1] 3.6e+09
Para corregir su código, conviértalo en una representación en coma flotante:
function (N)
{
for(i in as.single(1:N)) {
y <- i*i
}
}
Y sobre el tiempo:
fn1 <- function (N) {
for(i in as.numeric(1:N)) { y <- i*i }
}
fn2 <- function (N) {
i=1
while (i <= N) {
y <- i*i
i <- i + 1
}
}
system.time(fn1(60000))
# user system elapsed
# 0.06 0.00 0.07
system.time(fn2(60000))
# user system elapsed
# 0.12 0.00 0.13
Y ahora sabemos que for-loop es más rápido que while-loop. No puede ignorar las advertencias durante el tiempo.