[R] Floating point precision causing undesireable behaviour when printing as.POSIXlt times with microseconds?
Jim Holtman
jholtman at gmail.com
Thu Apr 25 11:25:02 CEST 2013
FAQ 7.31
also if you are using POSIXct for current dates, the resolution is down to about a milliseconds.
Sent from my iPad
On Apr 24, 2013, at 13:57, "O'Hanlon, Simon J" <simon.ohanlon at imperial.ac.uk> wrote:
> Dear list,
> When using as.POSIXlt with times measured down to microseconds the default format.POSIXlt seems to cause some possibly undesirable behaviour:
>
> According to the code in format.POSIXlt the maximum accuracy of printing fractional seconds is 1 microsecond, but if I do;
>
> options( digits.secs = 6 )
> as.POSIXlt( 1.000002 , tz="", origin="1970-01-01")
> as.POSIXlt( 1.999998 , tz="", origin="1970-01-01")
> as.POSIXlt( 1.999999 , tz="", origin="1970-01-01")
>
> I return respectively:
> [1] "1970-01-01 01:00:01.000002 BST"
> [1] "1970-01-01 01:00:01.999998 BST"
> [1] "1970-01-01 01:00:01 BST"
>
> If options( digits.secs = 6 ) should I not expect to be able to print 1.999999 seconds? This seems to be caused by the following code fragment in format.POSIXlt:
>
> np <- getOption("digits.secs")
> if (is.null(np))
> np <- 0L
> else np <- min(6L, np)
> if (np >= 1L)
> for (i in seq_len(np) - 1L) if (all(abs(secs - round(secs,
> i)) < 1e-06)) {
> np <- i
> break
> }
>
> Specifically
> for (i in seq_len(np) - 1L) if (all(abs(secs - round(secs,
> i)) < 1e-06))
> Which in the case of 1.999999 seconds will give:
>
> options( scipen = 10 )
> np <- 6
> sapply( seq_len(np) - 1L , function(x) abs(1.999999 - round(1.999999, x)) )
>
> [,1] [,2] [,3] [,4] [,5] [,6]
> [1,] 0.000001 0.000001 0.000001 0.000001 0.000001 0.000001
>
> The logical test all( ... < 1e-06) should evaluate to FALSE but due to floating point precision it evaluates TRUE:
>
> sprintf( "%.20f" , abs(1. 999999 - round(1. 999999,5)))
> [1] "0.00000099999999991773"
>
> If instead of:
>
> for (i in seq_len(np) - 1L) if (all(abs(secs - round(secs,
> i)) < 1e-06))
>
> in format.POSIXlt we had a comparison value that was half the minimum increment:
>
> for (i in seq_len(np) - 1L) if (all(abs(secs - round(secs,
> i)) < 5e-07))
>
> This behaviour disappears:
>
> mod.format.POSIXlt( as.POSIXlt( 1.999999 , tz="", origin="1970-01-01") )
> [1] "1970-01-01 01:00:01.999999"
>
> But I am unsure if the original behaviour is what I should expect given the documentation (I have read it and I can't see a reason to expect 1.999999 to round down to 1). And also if changing the formatting function would have other undesirable consequences?
>
> My sessionInfo():
> R version 3.0.0 (2013-04-03)
> Platform: x86_64-w64-mingw32/x64 (64-bit)
>
> locale:
> [1] LC_COLLATE=English_United Kingdom.1252
> [2] LC_CTYPE=English_United Kingdom.1252
> [3] LC_MONETARY=English_United Kingdom.1252
> [4] LC_NUMERIC=C
> [5] LC_TIME=English_United Kingdom.1252
>
> attached base packages:
> [1] stats graphics grDevices utils datasets methods base
>
>
>
> Thank you,
>
>
> Simon
>
>
> ------------------------------------
> Simon O'Hanlon
> Postgraduate Researcher
>
> Helminth Ecology Research Group
> Department of Infectious Disease Epidemiology
> Imperial College London
> St. Mary's Hospital, Norfolk Place,
> London, W2 1PG, UK
>
> Office: +44 (0) 20 759 43229
> ------------------------------------
>
>
> [[alternative HTML version deleted]]
>
> ______________________________________________
> R-help at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
More information about the R-help
mailing list