Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Unexpected level of "precision" in mod function

    Hi Statalist,


    I have been using numerical local macros to store "instructions" on how to slice strings using the substr function, where the number before the decimal point refers to the starting point and the decimal fraction refers to the length of the substring. This is really just by means of explaining my examples, the real puzzle and the reason for this post is very unexpected behaviour of mod. To wit,

    Code:
    local a = 5.02
    di substr("abcdefghijklm",int(`a'),mod(`a',1)*100) // expect ef
    results in an unexpected "e" rather than the "ef," that I would expect based on the expected expansion of the macros as substr("abcdefghijklm",5,2). Debugging steps to pin point the trouble maker:

    Code:
    di mod(`a',1)*100         // expect 2
    results in the expected 2, but

    Code:
    local b = mod(`a',1)*100  
    di "`b'"                  // expect 2
    outputs 1.999999999999957. Since substr expects integers as length, it makes sense that it truncates the value to 1, thus resulting in the single letter output of the initial command.

    Now, in the first order it puzzles me why mod would return such an odd result. Can somebody please explain that, so I can in the future avoid such pitfalls (it took me a frustratingly long time to find this, especially since my first debugging step seemed to confirm that there was nothing wrong with my code). I have now wrapped the mod in a round as a workaround, but would prefer a proper fix. In the second order it would be interesting to know why the first debug step (displaying the mod result directly) returns a different result than first assigning it to a macro, but that's purely for curiosity.

    Thanks,
    Christian

  • #2
    The main issue here is that numbers like .02 cannot be held exactly as binary numbers. There is no exact approximation to 0.02 in binary.

    This carries part of the story.

    FAQ . . . . . . . . . . . . . . . . . . . Results of the mod(x,y) function
    . . . . . . . . . . . . . . . . . . . . . N. J. Cox and T. J. Steichen
    4/15 Why does the mod(x,y) function sometimes give
    puzzling results?
    Why is mod(0.3,0.1) not equal to 0?
    https://www.stata.com/support/faqs/d.../mod-function/

    Further, display with no format specified usually rounds somewhat. The default format bears false witness here.

    Code:
    . di mod(5.02, 1) * 100
    2
    
    . di %21x  mod(5.02, 1) * 100
    +1.fffffffffff40X+000
    
    . di %21x 2
    +1.0000000000000X+001
    Finally, locals don't carry as much precision as scalars, not that scalars can solve the main problem.
    Last edited by Nick Cox; 24 Nov 2017, 17:18.

    Comment

    Working...
    X