6
$\begingroup$

Why does adding 6.1000000 seconds to a DateObject display as having added 6.099?

Mathematica notebook picture

If I copy the Out[20] element from this picture, it contains the correct value:

DateObject[{2014, 11, 7}, TimeObject[{8, 0, 6.1}], CalendarType -> "Gregorian"]

...but why does it display as 6.099 instead of 6.100?

More to the point, how can I make it display the correct answer?

$\endgroup$

3 Answers 3

3
$\begingroup$

This is the only 'fix' I could find.

Initialize the following:

$DateStringFormat = {"Year", "-", "Month", "-", "Day", "T", "Hour", ":", "Minute", ":", "SecondExact"};

System`DateStringDump`convertDateStringForms[{__, s_}, _, _, "Millisecond"] := 
  ToString[Floor[1000000 Round[FractionalPart[s], .00001]]]

Run your command:

DateObject[{2014, 11, 7, 8, 0, 0}] + Quantity[6.100000, "Second"]

enter image description here

$\endgroup$
4
  • 1
    $\begingroup$ Why not define a custom format: SystemDateStringDumpconvertDateStringForms[{__, s_}, _, _, "mysecpart"] := ToString[Floor[1000000 Round[FractionalPart[s], .00001]]] and then $DateStringFormat = {"Year", "-", "Month", "-", "Day", "T", "Hour", ":", "Minute", ":", "Second", ".", "mysecpart"}. $\endgroup$
    – Michael E2
    Commented Nov 7, 2014 at 23:36
  • 1
    $\begingroup$ Or do the seconds directly: SystemDateStringDumpconvertDateStringForms[{__, s_}, _, _, "mysec"] := StringDrop[ToString@NumberForm[6.1, {8, 6}, NumberPadding -> {"0", "0"}], 1]. Not sure why M won't pad in the way everybody wants (i.e., StringDrop should be unnecessary). $\endgroup$
    – Michael E2
    Commented Nov 7, 2014 at 23:52
  • $\begingroup$ Chip, I used $DateStringFormat = {"Year", "-", "Month", "-", "Day", "T", "Hour", ":", "Minute", ":", "SecondExact"} SystemDateStringDumpconvertDateStringForms[{__, s_}, _, _, "Millisecond"] := ToString[Floor[1000000 Round[FractionalPart[s], .00001]]] DateObject[{2014, 11, 7, 8, 0, 0}] + Quantity[6.100000, "Second"] DateObject[{2014, 11, 7, 8, 0, 0}] + Quantity[6.0000101, "Second"], which worked great for the 6.100000 example, but it renders 6.0000101 as 6.10. ?? $\endgroup$ Commented Nov 8, 2014 at 0:26
  • $\begingroup$ I was wrong in my previous comment. It's going to be easier to explain with a picture. What is the appropriate way for me to do that? $\endgroup$ Commented Nov 8, 2014 at 0:51
1
$\begingroup$

This boils down to floating point error.

In binary, 0.1 does not have a finite decimal expansion, so your computer must round.

This is a problem at a hardware level and can only be fixed by setting a precision higher than machine precision.

Here is what the fractional part of your float really looks like:

FractionalPart[6.1] // FullForm
(* 0.09999999999999964` *)

Here is what the fractional part of a higher precision number looks like:

FractionalPart[6.1`20] // FullForm
(* 0.1`18.214670164989236 *)

(The number after the ` is the precision)

$\endgroup$
1
  • 1
    $\begingroup$ Chip, thank you very much. How can I make it render as ".1"; actually, I'd like it to render as ".100000". ...Another problem I have is that all my work is in microseconds. $\endgroup$ Commented Nov 7, 2014 at 21:37
1
$\begingroup$

Here is the answer that, with @Chip's and @Michael's help, I came to:

$DateStringFormat = {"Year", "-", "Month", "-", "Day", " ", "Hour", ":", "Minute", ":", "Second", ".", "Foo"};
System`DateStringDump`convertDateStringForms[{__, s_}, _, _, "Foo"] := Module[{n = 6}, StringTake[ToString[PaddedForm[N[Round[s, 10^-n]], {30, n}]], -n]];
DateObject[{2014, 11, 7, 8, 0, 0}] + Quantity[6.100000, "Second"]
DateObject[{2014, 11, 7, 8, 0, 0}] + Quantity[6.0000107, "Second"]
DateObject[{2014, 11, 7, 8, 0, 0}] + Quantity[6.0000108, "Second"]
DateObject[{2014, 11, 7, 8, 0, 0}] + Quantity[6.12345671, "Second"]
DateObject[{2014, 11, 7, 8, 0, 0}] + Quantity[6.12345672, "Second"]

Still, two things bother me: (1) I can't find documentation about "DateStringDump" in the Mathematica documentation, or anywhere on Google! (2) Why does Round[_,10^-6] yield .0000107→.000010 and .0000108→.000011; and why .12345671→.123456 and .12345672→.123457? I see no pattern here. ...Maddening.

$\endgroup$
5
  • $\begingroup$ (1) There is a name for those sorts of commands: "undocumented". :) (2) I get 0.0000107 → 0.000011. $\endgroup$
    – Michael E2
    Commented Nov 10, 2014 at 22:03
  • $\begingroup$ @MichaelE2, understood on point 1, although I'm curious where someone learns of its existence. On point 2, I do too, when I use PaddedForm[N[Round[{6.0000104, 6.0000105, 6.0000106, 6.0000107}, 10^-6]], {10,6}] ...but not when I use the code shown above. $\endgroup$ Commented Nov 10, 2014 at 22:52
  • 1
    $\begingroup$ A few ways: ?*`*key* etc., foo = Trace[expr, TraceInternal -> True]; (loads of output consisting of evaluation chains, which takes some patience and strategy to find the important bit), LinkSnooper, and some of the contributors here work at Wolfram and just know things. There is also guessing, which works sometimes because Mathematica has a certain "style." In fact, I guessed at my comment to Chip Hurst's answer, checked it out, and what do you know, it worked. $\endgroup$
    – Michael E2
    Commented Nov 11, 2014 at 0:09
  • $\begingroup$ And I forgot this one: mathematica.stackexchange.com/questions/1742/… $\endgroup$
    – Michael E2
    Commented Nov 12, 2014 at 17:17
  • $\begingroup$ @CaryMillsap It looks like there is rounding errors that I alluded to in one of my answers when adding the DateObject and the Quantity. One way around that is to do DateObject[{2014, 11, 7, 8, 0, 6.0000107}]. $\endgroup$
    – Greg Hurst
    Commented Nov 14, 2014 at 16:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.