1

I'm puzzled by an ambiguity with respect to the representation/storage of micro-/milliseconds in class POSIXlt:

Printing the POSIXlt object shows different micro-/millisecond digits as a query of the respective attribute (last digit differs)

Maybe this makes perfect sense, but I find it kind of strange. Could someone explain this to me?

Microseconds

# Change digits for seconds >> microseconds
opts <- options(digits.secs=6)
x <- "2012-07-30 12:10:09.123123"

posix <- as.POSIXlt(x, tz="Europe/Berlin")

> posix
[1] "2012-07-30 12:10:09.123122 Europe/Berlin"

> posix$sec
[1] 9.123123

Milliseconds

posix$sec <- round(posix$sec, 3)

> posix
[1] "2012-07-30 12:10:09.122 Europe/Berlin"

> posix$sec
[1] 9.123

# Undo option change
options(opts)

Also, this doesn't really add to claritiy (at least for me ;-))

opts <- options(digits.secs=6)
x <- "2012-07-30 12:10:09.123123"
posix <- as.POSIXlt(x, tz="Europe/Berlin")

> posix
[1] "2012-07-30 12:10:09.123122 Europe/Berlin"
> posix$sec
[1] 9.123123

When manually manipulating the 'sec' attribute the result seems to vary; I still don't really see the systematic here, but adding an extra digit - preferably a 5 as pointed out by Aaaron - seems to get the desired result:

# Workaround: extra digit
posix$sec <- posix$sec+0.0000005
> posix
[1] "2012-07-30 12:10:09.123123 Europe/Berlin"

posix$sec <- 9.123122
> posix
[1] "2012-07-30 12:10:09.123122 Europe/Berlin"
posix$sec <- posix$sec+0.0000005
> posix
[1] "2012-07-30 12:10:09.123122 Europe/Berlin"

posix$sec <- 9.123124
> posix
[1] "2012-07-30 12:10:09.123124 Europe/Berlin"
posix$sec <- posix$sec+0.0000005
> posix 
[1] "2012-07-30 12:10:09.123124 Europe/Berlin"

posix$sec <- 9.123125
> posix
[1] "2012-07-30 12:10:09.123124 Europe/Berlin"
posix$sec <- posix$sec+0.0000005
> posix
[1] "2012-07-30 12:10:09.123125 Europe/Berlin"

posix$sec <- 9.123126
> posix
[1] "2012-07-30 12:10:09.123125 Europe/Berlin"
posix$sec <- posix$sec+0.0000005
> posix
[1] "2012-07-30 12:10:09.123126 Europe/Berlin"

options(opts)

Session Info

R version 2.14.1 (2011-12-22)
Platform: i386-pc-mingw32/i386 (32-bit)

locale:
[1] LC_COLLATE=German_Germany.1252  LC_CTYPE=German_Germany.1252   
[3] LC_MONETARY=German_Germany.1252 LC_NUMERIC=C                   
[5] LC_TIME=German_Germany.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

EDIT 2012-07-31

Thanks to Aaron I think I found a workaround that does the trick for me by simply adding an extra digit that's used internally for rounding to the next-off digit to the left.

rcs
  • 67,191
  • 22
  • 172
  • 153
Rappster
  • 12,762
  • 7
  • 71
  • 120
  • Can you post your `sessionInfo()`? Note that I cannot replicate your first example: `as.POSIXlt(x, tz="Europe/Berlin")` returns `"2012-07-30 12:10:09.123123 Europe/Berlin"` for me. – nograpes Jul 30 '12 at 16:47
  • Just a sec, I'll update the post – Rappster Jul 30 '12 at 16:53
  • Just noted it's time to update R ;-) I'll check if I get the same behavior with R-2.15.1 – Rappster Jul 30 '12 at 16:55
  • No, for me it's the same for R-2.15.1 – Rappster Jul 30 '12 at 16:57
  • Okay, I am able to replicate the problem *only in 32-bit R*. I suspect something is going on with the number of digits that can be represented... – nograpes Jul 30 '12 at 17:04
  • Okay, cool (and not cool ;-)) Thanks for shedding some more light on this! – Rappster Jul 30 '12 at 17:08
  • This may be simply an issue of rounding when printing, which has been asked/answered several times on this site, so you should be able to find something by searching. – Joshua Ulrich Jul 30 '12 at 17:34
  • This what came in from the help-list: "FAQ 7.31 In floating point, you get about 15 digits of precision. If you look at the value of time for today you will see: 1343668783 If you add 5 more digits after the decimal point, you will see that there is not resolution to a microsecond level. I usually assume that I can get millisecond resolution from POSIXct values." – Rappster Jul 30 '12 at 17:54
  • @nograpes: just to clarify, since you couldn't replicate the behavior there: is the floating point accuracy greater on 64bit systems? – Rappster Jul 30 '12 at 17:56

1 Answers1

3

This is because R rounds down for display of times (just like a stopwatch would do). So when printing the entire time object, it rounds down. But when printing just part of it, it's no longer a time object, so standard rounding applies.

Floating-point representation makes this even more obvious as if a number is represented as 0.39999999999 (or whatever the binary equivalent would be) it will display as 0.3 even though within the floating-point tolerance, it's equal to 0.4.

To get usual rounding behavior add 0.0005 (to get three decimal places) before display.

See How R formats POSIXct with fractional seconds for more details.

Community
  • 1
  • 1
Aaron left Stack Overflow
  • 36,704
  • 7
  • 77
  • 142
  • But wouldn't that also be the case for `.123124` then? According to your answer, R should still round down, but doesn't. – Rappster Jul 30 '12 at 18:56
  • I see where you set it to .123124 and it displays .123124, but not anywhere where it's not rounding down. Can you clarify? – Aaron left Stack Overflow Jul 30 '12 at 22:17
  • I updated my post a little. I feel that I still don't understand when floating-point numbers are rounded (down) and when they're not (e.g. '.123123': rounding, '.123124': no rounding etc.). Thanks for helping me out on this! – Rappster Jul 31 '12 at 07:21
  • Still don't really get the internals of this, but thanks for the pointer to your other post! Seems like there are numerous workarounds. – Rappster Jul 31 '12 at 08:01
  • 1
    They're always rounded down. But sometimes the number is stored internally as a little bit more than the number you put in (that's when you get the number you put in), and sometimes a little bit less (that's when you get one unit less), depending on the floating-point representation. Also, to get usual rounding behavior add 0.0005, not 0.0001 (to get three decimal places). [I added that to the answer also.] – Aaron left Stack Overflow Jul 31 '12 at 11:42
  • Thanks a lot, again something learned ;-) This is what makes SO so great! – Rappster Jul 31 '12 at 12:29