[Rd] Floating Point with POSIXct
John Muschelli
mu@che|||j2 @end|ng |rom gm@||@com
Thu Mar 3 21:07:35 CET 2022
That’s a good point. I think that’s fair and why rounding may not be the
appropriate default. Oddly enough, I think 1:59:60 may be more appropriate
though wrong. The way the seconds are separated in POSIXlt however, I
don’t think that would ever happen, but the big downside would be if that
would round to 1:59:59.00
On Thu, Mar 3, 2022 at 2:38 PM Duncan Murdoch <murdoch.duncan using gmail.com>
wrote:
> On 03/03/2022 11:52 a.m., Martin Maechler wrote:
> >>>>>> John Muschelli
> >>>>>> on Thu, 3 Mar 2022 11:04:05 -0500 writes:
> >>>>>> John Muschelli
> >>>>>> on Thu, 3 Mar 2022 11:04:05 -0500 writes:
> >
> > > I see in ?POSIXct and I'm trying to understand the note:
> > >> Classes "POSIXct" and "POSIXlt" are able to express fractions of
> a second. (Conversion of fractions between the two forms may not be exact,
> but will have better than microsecond accuracy.)
> >
> > > Mainly, I'm trying to understand printing of POSIXct with
> fractional
> > > seconds. I see print.POSIXct calls format.POSIXct and eventually
> > > calls format.POSIXlt, which then takes into account `digits.secs`
> for
> > > printing. The format uses %OS3, which strptime indicates (*
> added):
> >
> > >> Specific to R is %OSn, which for output gives the seconds
> *truncated* to 0 <= n <= 6 decimal places (and if %OS is not followed by a
> digit, it uses the setting of getOption("digits.secs"), or if that is
> unset, n = 0).
> >
> > > So I'm seeing it truncates the seconds to 3 digits, so I think
> that is
> > > why the below is printing 0.024.
> >
> > > I think this is especially relevant even if you set
> > > `options(digits.secs = 6)`, then the code in
> > > format.POSIXlt would still return np=3 as the following condition
> > > would break at i = 3
> >
> > > for (i in seq_len(np) - 1L)
> > > if (all(abs(secs - round(secs, > i)) < 1e-06)) {
> > > np <- i
> > > break
> > > }
> >
> > > as sub_seconds - round(sub_seconds,3) < 1e-06. This seems to be
> > > expected behavior given the docs, but would any consider this a
> bug?
> >
> >
> > > Example:
> >
> > > options(digits.secs = 4)
> > > x = structure(947016000.025, class = c("POSIXct", "POSIXt"),
> tzone = "UTC")
> >
> > I think you've fallen into the R FAQ 7.31 trap :
> >
> >> ct <- 947016000.025
> >> ct %% 1
> > [1] 0.02499998
> >>
> >
> > Of course, the issue may still be somewhat interesting, ...
> >
> > Yes, POSIXct is of limited precision and I think the help page
> > you mentioned did document that that's one reason for using
> > POSIXlt instead, as there, sub second accuracy can be much better.
> >
> > But FAQ 7.31 and the fact that all numbers are base 2 and in
> > base 2, no decimal <n>.025 can be represented in full accuracy.
> >
> > Also, as you've noticed the R POSIX[cl]t code just truncates,
> > i.e. rounds towards 0 unconditionally, and I tend to agree that it
> > should rather round than truncate.
>
> If you print the hour and minute at 01:59:59, you get 1 and 59, not 2
> and 0. That may be the motivation for doing the same for fractional
> seconds. Should 1:59:59.9 really print as 2:00:00?
>
> Duncan Murdoch
> >
> > But we should carefully separate the issues here, from the
> > underlying inherent FAQ 7.31 truth that most decimal numbers in
> > a computer are not quite what they look like ...
> >
> > Martin Maechler
> > ETH Zurich and R Core Team (also author of the CRAN package 'round')
> >
> >
> > > summary(x, digits = 20)
> > > #> Min. 1st Qu.
> Median
> > > #> "2000-01-04 20:00:00.024" "2000-01-04 20:00:00.024"
> "2000-01-04 20:00:00.024"
> > > #> Mean 3rd Qu.
> Max.
> > > #> "2000-01-04 20:00:00.024" "2000-01-04 20:00:00.024"
> "2000-01-04 20:00:00.024"
> > > x
> > > #> [1] "2000-01-04 20:00:00.024 UTC"
> > > format.POSIXct(x, format = "%Y-%m-%d %H:%M:%OS3")
> > > #> [1] "2000-01-04 20:00:00.024"
> > > format.POSIXct(x, format = "%Y-%m-%d %H:%M:%OS4")
> > > #> [1] "2000-01-04 20:00:00.0249"
> > > sub_seconds = as.numeric(x) %% 1
> > > sub_seconds
> > > #> [1] 0.02499998
> > > round(sub_seconds, 3)
> > > #> [1] 0.025
> >
> > > rounded = as.POSIXct(
> > > floor(as.numeric(x)) +
> > > round(as.numeric(x) %% 1, 3),
> > > origin = "1970-01-01")
> > > rounded
> > > #> [1] "2000-01-04 20:00:00.024 UTC"
> > > as.numeric(rounded) %% 1
> > > #> [1] 0.02499998
> >
> > > R.version
> > > _
> > > platform x86_64-pc-linux-gnu
> > > arch x86_64
> > > os linux-gnu
> > > system x86_64, linux-gnu
> > > status
> > > major 4
> > > minor 1.2
> > > year 2021
> > > month 11
> > > day 01
> > > svn rev 81115
> > > language R
> > > version.string R version 4.1.2 (2021-11-01)
> > > nickname Bird Hippie
> >
> >
> >
> > > Best,
> > > John
> >
> > > ______________________________________________
> > > R-devel using r-project.org mailing list
> > > https://stat.ethz.ch/mailman/listinfo/r-devel
> >
> > ______________________________________________
> > R-devel using r-project.org mailing list
> > https://stat.ethz.ch/mailman/listinfo/r-devel
>
> --
Best,
John
[[alternative HTML version deleted]]
More information about the R-devel
mailing list