O'Hanlon, Simon J
2013-Apr-24 17:57 UTC
[R] Floating point precision causing undesireable behaviour when printing as.POSIXlt times with microseconds?
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]]
Jim Holtman
2013-Apr-25 09:25 UTC
[R] Floating point precision causing undesireable behaviour when printing as.POSIXlt times with microseconds?
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.
Maybe Matching Threads
- Possible bug in class 'POSIXlt' when including microseconds?
- strftime fails on POSIXct objects (PR#10695)
- Microseconds for a zoo object?
- Alternative to some recently changed parts of dates.R and datetime.R
- Label rows of table by factor level for groups of factors