Announcement

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

  • forvalues: unexpected value of a looping local: 81/100=.8100000000000001

    Dear Stata list users,

    I want to loop over values d=0(0.01)0.2 and d2= 0.80(0.01)1
    I already know that I should only loop over integers and then transform the looping local within the loop.
    To identify outputs in my logfile, I call Stata to display the actual value of the looping local and thereby remarked that the loopin local does not always have the value it should have.

    Code:
    tempname d d2
    forvalues dd = 0(1)20{          
    scalar `d' = `dd'/100                                
    forvalues dd2 = 80(1)95{          
    scalar `d2' = `dd2'/100                                     
    di "*****************************************************************************"
    di "*** delta=`=`d'', delta2=`=`d2'' *********"
    di "--------------------------------------------------------------------------------------"
    }
    }
    It works out for the first but not for the second loop.
    For the loop over dd2 = 80(1)100, I get two strange outputs displayed:
    *** delta=`=`d'', delta2=.8100000000000001 *********"
    *** delta=`=`d'', delta2=.9399999999999999 *********"
    Though it obviously should be 0.81 and 0.94, respectively.

    Therefore, I
    (1) tried to reformulate the loop, mainly changing order of the loops and naming of the locals, with the same result.
    (2) restarted the machine and tried again - same result
    (3) took my other machine: I get slightly different output, but still not satisfactory:
    delta2=.9300000000000001 and delta2=8100000000000001.
    And again, no problems with the loop over dd=0(1)20.
    (4) BUT when I differently call for displaying the value of the looping local, I get the right AND the wrong numbers.

    Code:
    tempname d d2
    forvalues dd = 20(1)20{          
    scalar `d' = `dd'/100                                
    forvalues dd2 = 80(1)95{          
    scalar `d2' = `dd2'/100                                     
    di "*****************************************************************************"
    di "*** delta=`=`d'', delta2=`=`d2'' *********"
    di "--------------------------------------------------------------------------------------"
    di "delta2= `d2'        "
    di "delta2= `=`d2''     "
    di "delta2= `=`dd2'/100'"
    di "delta2= `dd2'/100   "
    }
    }
    Of course, I placed the "" differently and therewith get different output displayed, but the problem remains the same

    I would really love to know
    (1) why do I get the odd numbers, though I loop over integers?
    (2) why do I get the odd numbers always for the same value of the looping local, but depending on the machine I use?
    (3) why do I get contradictory outputs for the same value of the looping local, depending on how I ask to display it?
    (4) what could I do to solve this issue?

    Thank you in advance for your precious time.
    Susanne

    NB: I use Stata 15.1

  • #2
    This happens because the numbers 83/100 and 91/100 (and many of the others you are using) have no exact representation in finite binary notation. (Just as 1/3 has no exact finite decimal notation.) Stata uses the closest number it can represent within the number of binary places it has available for calculations. Usually -display-, when encountering such numbers, will round them to something that looks more or less like you want to see, but this mechanism is imperfect. I cannot explain why it happens with those particular values and not the others. Suffice it to say that -display- just doesn't grasp that this number is intended to be 0.83 or 0.91, so it shows you the number in all its detail.

    In terms of solving this, there are two separate issues. If by solving it you mean getting Stata to actually use the exact values 0.81 and 0.93, that is impossible. But surely you realize that the discrepancy between .8100000000000001 and 0.81 is too small to matter for any real-world purpose. So the unsolvability of that aspect of this problem is really unimportant. If, however, you wish not to be reminded of the approximation inherent in floating point arithmetic and would prefer to only be shown the numbers at 2 decimal places of precision, change -display whatever- to -display %3.2f whatever- and Stata will oblige.

    Read -help precision- for more information.

    Added: What is happening with 0.81 is also happening, behind the scenes, with all of the other numbers. You just aren't seeing it because -display- was able to "cover it up." But if you force -display- to show you the full details, you will see it:

    Code:
    . display %22.21f =81/100
    0.810000000000000053291
    
    . display %22.21f =82/100
    0.819999999999999951150
    Again, the discrepancy between the actual values and the intended ones is not large enough to matter for real world purposes.


    Last edited by Clyde Schechter; 12 Feb 2019, 17:33.

    Comment


    • #3
      Thank you for the explication, Clyde.

      Comment

      Working...
      X