[r] For-loop vs while loop in R

I have noticed a curious thing whilst working in R. When I have a simple program that computes squares from 1 to N implemented using for-loop and while-loop the behaviour is not the same. (I don't care about vectorisation in this case or apply functions).

fn1 <- function (N) 
{
    for(i in 1:N) {
        y <- i*i
    }
}

AND

fn2 <- function (N) 
{
    i=1
    while(i <= N) {
        y <- i*i
        i <- i + 1
    }
}

The results are:

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 

Now we know that for-loop is faster, my guess is because of pre allocation and optimisations there. But why does it overflow?

UPDATE: So now trying another way with vectors:

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

So Perhaps its a funky memory issue? I am running on OS X with 4Gb of memory and all default settings in R. This happens in 32- and 64-bit versions (except that times are faster).

Alex

This question is related to r for-loop floating-point while-loop

The answer is


Because 1 is numeric, but not integer (i.e. it's a floating point number), and 1:6000 is numeric and integer.

> print(class(1))
[1] "numeric"
> print(class(1:60000))
[1] "integer"

60000 squared is 3.6 billion, which is NOT representable in signed 32-bit integer, hence you get an overflow error:

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

3.6 billion is easily representable in floating point, however:

> as.single(60000)*as.single(60000)
[1] 3.6e+09

To fix your for code, convert to a floating point representation:

function (N)
{
    for(i in as.single(1:N)) {
        y <- i*i
    }
}

The variable in the for loop is an integer sequence, and so eventually you do this:

> y=as.integer(60000)*as.integer(60000)
Warning message:
In as.integer(60000) * as.integer(60000) : NAs produced by integer overflow

whereas in the while loop you are creating a floating point number.

Its also the reason these things are different:

> seq(0,2,1)
[1] 0 1 2
> seq(0,2)
[1] 0 1 2

Don't believe me?

> identical(seq(0,2),seq(0,2,1))
[1] FALSE

because:

> is.integer(seq(0,2))
[1] TRUE
> is.integer(seq(0,2,1))
[1] FALSE

And about timing:

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

And now we know that for-loop is faster than while-loop. You cannot ignore warnings during timing.


Examples related to r

How to get AIC from Conway–Maxwell-Poisson regression via COM-poisson package in R? R : how to simply repeat a command? session not created: This version of ChromeDriver only supports Chrome version 74 error with ChromeDriver Chrome using Selenium How to show code but hide output in RMarkdown? remove kernel on jupyter notebook Function to calculate R2 (R-squared) in R Center Plot title in ggplot2 R ggplot2: stat_count() must not be used with a y aesthetic error in Bar graph R multiple conditions in if statement What does "The following object is masked from 'package:xxx'" mean?

Examples related to for-loop

List append() in for loop Prime numbers between 1 to 100 in C Programming Language Get current index from foreach loop how to loop through each row of dataFrame in pyspark TypeScript for ... of with index / key? Is there a way in Pandas to use previous row value in dataframe.apply when previous value is also calculated in the apply? Python for and if on one line R for loop skip to next iteration ifelse How to append rows in a pandas dataframe in a for loop? What is the difference between ( for... in ) and ( for... of ) statements?

Examples related to floating-point

Convert list or numpy array of single element to float in python Convert float to string with precision & number of decimal digits specified? Float and double datatype in Java C convert floating point to int Convert String to Float in Swift How do I change data-type of pandas data frame to string with a defined format? How to check if a float value is a whole number Convert floats to ints in Pandas? Converting Float to Dollars and Cents Format / Suppress Scientific Notation from Python Pandas Aggregation Results

Examples related to while-loop

While, Do While, For loops in Assembly Language (emu8086) MySQL Insert with While Loop Python loop to run for certain amount of seconds How to break a while loop from an if condition inside the while loop? How to find sum of several integers input by user using do/while, While statement or For statement Python: How to keep repeating a program until a specific input is obtained? Creating multiple objects with different names in a loop to store in an array list ORA-06502: PL/SQL: numeric or value error: character string buffer too small How to break out of a loop in Bash? for or while loop to do something n times