Solved
Posts: 4,736

# Losing precision

[ Edited ]

Does anyone have an explanation why in version 1 in the code below I'm losing precision but things work for version 2?

``````/* version 1 */
%Let date1= "05JAN2017:09:58:57.822"dt;
%let date2=%sysfunc(sum(&date1,-10),datetime26.3);
%put &=date1;
%put Losing precision:  &=date2;

/* version 2 */
%Let date1= 1799229537.822;
%let date2=%sysfunc(sum(&date1,-10),datetime26.3);
%put &=date1;
%put Full precision:  &=date2;``````

Accepted Solutions
Solution
‎01-08-2017 04:24 PM
Super Contributor
Posts: 320

## Re: Losing precision

[ Edited ]

Actually - I think that is the pointer to the real problem...

``````
data _null_;
date1a= "05JAN2017:09:58:57.822"dt;
date1b= 1799229537.822;

put date1a=;
put date1b=;

put date1a= best32.;
put date1b= best32.;

put date1a=  binary64.;
put date1b=  binary64.;

date2a = sum(date1a,-10);
date2b = sum(date1b,-10);

put date2a=  binary64.;
put date2b=  binary64.;

run;``````

Somewhere in the macro variable assignment, BEST12. is being used.  BEST12. will yield a rounded value to 1 place.

I don't see a way to get SAS to not do that; for example, even this won't listen:

``````%Let date1= %sysfunc(sum("05JAN2017:09:58:57.862342"dt),best32.);
%put &=date1;
``````

Presumably because the conversion happens immediately seeing the constant and resolving it and bringing it into the macro facility.  So you'll have to do a workaround like data _null_ says, or perhaps a bit simpler,

``````%Let date1= 05JAN2017:09:58:57.822;
%let date2= %sysfunc(inputn(&date1.,datetime,26));
%put &=date2;
``````

(easier if you leave off all the other stuff and just store the date-as-text in date1).

All Replies
Community Manager
Posts: 3,424

## Re: Losing precision

I don't know the answer, but guessing it has to do with the macro processor as you're assigning the values in %LET.

``````%Let date1= "05JAN2017:09:58:57.822"dt;
%let date1bin = %sysfunc(putn(&date1.,binary64.));
%Let date2= 1799229537.822;
%let date2bin = %sysfunc(putn(&date2.,binary64.));

%put &=date1;
%put &=date1bin;
%put &=date2;
%put &=date2bin;
``````

Yields two different values:

```36         %put &=date1;
DATE1="05JAN2017:09:58:57.822"dt
37         %put &=date1bin;
DATE1BIN=0100000111011010110011111000010000011000011100110011001100110011
38         %put &=date2;
DATE2=1799229537.822
39         %put &=date2bin;
DATE2BIN=0100000111011010110011111000010000011000011101001001101110100110```

Compare to DATA step:

``````data _null_;
date1a= "05JAN2017:09:58:57.822"dt;
date1b= 1799229537.822;

put date1a=  binary64.;
put date1b=  binary64.;

date2a = sum(date1a,-10);
date2b = sum(date1b,-10);

put date2a=  binary64.;
put date2b=  binary64.;

run;``````

Output (two pairs of identical values, initial values then the sum values):

```date1a=0100000111011010110011111000010000011000011101001001101110100110
date1b=0100000111011010110011111000010000011000011101001001101110100110
date2a=0100000111011010110011111000010000010101111101001001101110100110
date2b=0100000111011010110011111000010000010101111101001001101110100110```

Valued Guide
Posts: 505

## Re: Losing precision

A good question like this one is worth a thousand answers

Thanks Chris

I get the same result when using the same input.

Computers are not decimal machines.
Decimal to Binary to Decimal is not reversible.

/* version 1 */
%Let date1= 41DACF8418749BA6;
%let date2=%sysfunc(sum(%sysfunc(inputn(41DACF8418749BA6,hex16.)),-10),datetime26.3);
%put &=date1;
%put Loosing precision: &=date2;

/* version 2 */
%Let date1= 41DACF8418749BA6;
%let date2=%sysfunc(sum(%sysfunc(inputn(41DACF8418749BA6,hex16.)),-10),datetime26.3);
%put &=date1;
%put Full precision: &=date2;

LOG

108 /* version 1 */
109 %Let date1= 41DACF8418749BA6;
110 %let date2=%sysfunc(sum(%sysfunc(inputn(41DACF8418749BA6,hex16.)),-10),datetime26.3);
111 %put &=date1;
DATE1=41DACF8418749BA6
112 %put Loosing precision: &=date2;
Loosing precision: DATE2=05JAN2017:09:58:47.822
113 /* version 2 */
114 %Let date1= 41DACF8418749BA6;
115 %let date2=%sysfunc(sum(%sysfunc(inputn(41DACF8418749BA6,hex16.)),-10),datetime26.3);
116 %put &=date1;
DATE1=41DACF8418749BA6
117 %put Full precision: &=date2;
Full precision: DATE2=05JAN2017:09:58:47.822

Posts: 3,852

## Re: Losing precision

[ Edited ]

I don't know the reason but this rather SYSFUNC heavy expression does produce the correct result.

```%let date3=%sysfunc(sum(%sysfunc(inputn(%sysfunc(dequote(&date1)),datetime,26)),-10),datetime26.3);

NOTE: DATE3=05JAN2017:09:58:47.822```

Super Contributor
Posts: 320

## Re: Losing precision

[ Edited ]

It's in the conversion of the datetime constant I think:

``````
%Let date1= %sysevalf("05JAN2017:09:58:57.822"dt);``````

That already loses the extra characters.  Probably a question for SAS tech support as to why it happens - however the datetime constant is resolved must only take one decimal place for some reason.

Interestingly, it's not truly losing precision: look at this.

``````
%Let date1= %sysevalf("05JAN2017:09:58:57.862342"dt+0);``````

That rounds up - meaning SAS is doing this on purpose, this isn't a loss of precision situation.

Even more interestingly, I do not get the same results Chris does in the data step - at least, not when I go through CALL SYMPUTX:

``````
data _null_;
call symputx('date1',"05JAN2017:09:58:57.822"dt);
run;
%put &=date1;``````

Or even:

``````
data _null_;
x = "05JAN2017:09:58:57.822"dt;
put x=;
call symputx('date3',x);
run;
%put &=date3;``````

Both `x` and `&date3` have the rounded value.

Solution
‎01-08-2017 04:24 PM
Super Contributor
Posts: 320

## Re: Losing precision

[ Edited ]

Actually - I think that is the pointer to the real problem...

``````
data _null_;
date1a= "05JAN2017:09:58:57.822"dt;
date1b= 1799229537.822;

put date1a=;
put date1b=;

put date1a= best32.;
put date1b= best32.;

put date1a=  binary64.;
put date1b=  binary64.;

date2a = sum(date1a,-10);
date2b = sum(date1b,-10);

put date2a=  binary64.;
put date2b=  binary64.;

run;``````

Somewhere in the macro variable assignment, BEST12. is being used.  BEST12. will yield a rounded value to 1 place.

I don't see a way to get SAS to not do that; for example, even this won't listen:

``````%Let date1= %sysfunc(sum("05JAN2017:09:58:57.862342"dt),best32.);
%put &=date1;
``````

Presumably because the conversion happens immediately seeing the constant and resolving it and bringing it into the macro facility.  So you'll have to do a workaround like data _null_ says, or perhaps a bit simpler,

``````%Let date1= 05JAN2017:09:58:57.822;
%let date2= %sysfunc(inputn(&date1.,datetime,26));
%put &=date2;
``````

(easier if you leave off all the other stuff and just store the date-as-text in date1).

Posts: 4,736

## Re: Losing precision

[ Edited ]

Thank you all for your valuable input. ...and also thank you @ChrisHemedinger for fixing my spelling.

Even though I have very rarely to use fractional seconds in real life situations and there are multiple ways to code around this implicit rounding, I'm still going to raise a TechSupport track for this one. I'll keep you posted once I've got a "final" answer.

☑ This topic is solved.