BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
somebody
Lapis Lazuli | Level 10

I am computing the daily change/return of a series. In many cases, the value should be 0 because the value does not change. However, instead of 0, SAS produces extremely small values such as -3.76158E-37. What is going on? I read somewhere that sometimes the computer does that but cannot remember why/how. How do I address this issue apart from rounding the number such as 

change = round (value/value_lag1, 0.0000000001)

Not sure if it helps but the time series variable has an informat 12. and format best12.

 

toin the direction ofMore (Definitions, Synonyms, Translation)

1 ACCEPTED SOLUTION

Accepted Solutions
ballardw
Super User

The issue is called "precision" and all computers have limits as to how many decimal can be stored in binary form. Depending on how many bits a numeric value can be used to store values determines how many digits are accurately represented. The more calculations involved the more likely that you start loosing small amounts at the limits of storage and can generate internal round-off errors such as you see. With SAS the typical limit is 15 or 16 significant digits depending on operating system.

All irrational or repeating decimals have such an issue and never fit exactly. 1/3 is 0.3333333333333333 (until you get tired of typing 3 and it still goes on).

 

So if that is your need then controlling the result of your calculations by rounding, truncating or other approach may be required. You might find the FUZZ function of use as it returns the nearest integer if the value is within 1E-12 of an integer.

change = fuzz (value/value_lag1);

 

View solution in original post

3 REPLIES 3
ballardw
Super User

The issue is called "precision" and all computers have limits as to how many decimal can be stored in binary form. Depending on how many bits a numeric value can be used to store values determines how many digits are accurately represented. The more calculations involved the more likely that you start loosing small amounts at the limits of storage and can generate internal round-off errors such as you see. With SAS the typical limit is 15 or 16 significant digits depending on operating system.

All irrational or repeating decimals have such an issue and never fit exactly. 1/3 is 0.3333333333333333 (until you get tired of typing 3 and it still goes on).

 

So if that is your need then controlling the result of your calculations by rounding, truncating or other approach may be required. You might find the FUZZ function of use as it returns the nearest integer if the value is within 1E-12 of an integer.

change = fuzz (value/value_lag1);

 

Shmuel
Garnet | Level 18

Sas numeric variables are saved, even integers, as exponential.

 

You are computing daily change/return. Usually you need 2 decimal digits.

For reporting use a format like 12.2.

For checking is the value zero round or use the int() function.

FreelanceReinh
Jade | Level 19

Hi @somebody,

 

At first glance this looks like yet another rounding issue related to precision and numeric representation errors which have been discussed in a number of threads. However, your example is somewhat special in two ways:


  1. @somebody wrote:

    I am computing the daily change/return of a series. In many cases, the value should be 0 because the value does not change.


    If the value in the series really doesn't change, the standard formulas for change or return should not produce those tiny differences. So I suspect that the input values already are affected by rounding errors and only the formatted display ("best12.") makes them appear equal.

  2. Typically, the tiny differences between two numbers that "should actually be equal" amount to small integer multiples of the place value of the least significant bit. For example, in SAS on Windows and Unix platforms the place value of the least significant bit of a number x with 1 <= x < 2 (i.e., "order of magnitude 2**0") is 2**−52=2.2204...E−16. More generally, it's 2**(−52+k) for numbers in the order of magnitude 2**k. So it's plausible why, e.g., 0.8-0.1-0.7=2**-53 (Windows SAS) because the k for 0.8 and 0.7 is −1 (and −4 for 0.1).
    The fact that 2**−121=3.76158...E−37 suggests that your "extremely small values" were produced in the context of numbers in the order of magnitude 2**(−121+52)=2**−69=1.694...E−21, which is extremely small itself and obviously much smaller than what one would expect to see in financial time series.

It would be interesting to see an example of two (seemingly) equal values of your time series, the formula (and the operating system) used to compute the change or return and the resulting tiny difference.

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 3 replies
  • 1943 views
  • 0 likes
  • 4 in conversation