while variable the name loop how for examples example change r for-loop floating-point while-loop

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.