BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
arunrami
Pyrite | Level 9

Hi SASians,
 
I have noticed something weird today while using long int in SAS dataset, it is getting printed slightly different value
even after using format . I believed this is something related to scientific notation  E to real value goes wrong in PDV ..
or am I missing something here ??
Any suggestion and why it is like that ?
 
data dummy;
infile cards;
input a 30.;
format a 30.;
cards;
231512182813021801
run;
getting 231512182813021792 , expected value 231512182813021801.
 
 
Regards,
SAR

1 ACCEPTED SOLUTION

Accepted Solutions
FreelanceReinh
Jade | Level 19

Hi @arunrami,

 

Here are the details of what SAS did to your numeric literal 231512182813021801 (assuming a Windows or Unix operating system):

  1. Write the original integer in the binary system (e.g., the Windows calculator calc.exe can do this conversion):
    1100110110011111110001101010001001101111101101011001101001
    Note that it has 58 binary digits.
  2. Round the number to 53 significant binary digits:
    1100110110011111110001101010001001101111101101011001100000
    The last 58−53=5 original binary digits, 01001, started with 0 and hence have been rounded down. (This has the same effect as subtracting 01001, i.e. 9 in the decimal system, from the original number.) 
  3. Convert the number back to the decimal system. (Again, the Windows calculator can do this, but alternatively you can just add/subtract the amount by which the original number has been rounded up/down, see item 2: ...1801−9=...1792.)
    231512182813021792

The 53 bits mentioned in item 2 are the so called "implied bit" plus the 52 mantissa bits which SAS stores internally besides the 1+11 bits for the sign and exponent, respectively (see Numerical Accuracy in SAS Software [linked by yabwon already] for more details).

 

To avoid the loss of precision, you should store integers of this size in character variables, as Kurt Bremser has recommended. Using PROC DS2 or PROC FedSQL you can still handle them (up to certain limits, see BIGINT data type) as numeric values: see the old thread Convert large number for an example. Certain calculations can even be done digit by digit in a DATA step (example: Mod function with big number).

View solution in original post

7 REPLIES 7
Kurt_Bremser
Super User

SAS does not have the datatype longint (except in some special circumstances).

SAS stores all numbers in 8-byte real, which means that the maximum precision is about 15 decimal digits, and that causes the effect you see here.

 

For statistical analysis, such precision is not needed, and if you have something that is not in fact a number, but some kind of code (eg telephone numbers or SSN), you are better off storing it as character.

 


@arunrami wrote:

Hi SASians,
 
I have noticed something weird today while using long int in SAS dataset, it is getting printed slightly different value
even after using format . I believed this is something related to scientific notation  E to real value goes wrong in PDV ..
or am I missing something here ??
Any suggestion and why it is like that ?
 
data dummy;
infile cards;
input a 30.;
format a 30.;
cards;
231512182813021801
run;
getting 231512182813021792 , expected value 231512182813021801.
 
 
Regards,
SAR


 

arunrami
Pyrite | Level 9

Thanks for the reponse

, but I really want it as a number and also am fetching from database hence it would be better if I can store and see the result as it is..

and converting the datatype to character also doesn't seem to be solving the problem..find here

 

data fil;
set dummy;
b = put(a,20.); 
where a = 231512182813021801 ;
run;

 

 

is there any other way to read and print these kind of as it is ?

Kurt_Bremser
Super User

@arunrami wrote:

Thanks for the reponse

, but I really want it as a number and also am fetching from database hence it would be better if I can store and see the result as it is..

and converting the datatype to character also doesn't seem to be solving the problem..find here

 

data fil;
set dummy;
b = put(a,20.); 
where a = 231512182813021801 ;
run;

 

 

is there any other way to read and print these kind of as it is ?


Well, a has already lost precision, so converting it within SAS is useless. You need to import it as character in the first place.

And, as I already said, if it IS a number, such precision makes no sense in a statistics environment. It's another thing if you need the GDP of the USA down to cents, but we're not doing the national accounting here 😉

arunrami
Pyrite | Level 9
I got your point, it may not be significant when using it for statistics!,
but considering reporting, like taking data from source(for which we dont have any write access and just creating some report out of it, precision does matter !!

And I noted that value stored as an actual one in SAS memory , poroblem is only when I try to print/see it in dataset 😞
yabwon
Onyx | Level 15

Hi,

 

The 9,007,199,254,740,992 is max what SAS can store in 8 bytes on WIN or Linux. Please see the doc here:

https://documentation.sas.com/?docsetId=lrcon&docsetTarget=p0ji1unv6thm0dn1gp4t01a1u0g6.htm&docsetVe...

for details (section "Maximum Integer Size").

 

All the best

Bart

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



FreelanceReinh
Jade | Level 19

Hi @arunrami,

 

Here are the details of what SAS did to your numeric literal 231512182813021801 (assuming a Windows or Unix operating system):

  1. Write the original integer in the binary system (e.g., the Windows calculator calc.exe can do this conversion):
    1100110110011111110001101010001001101111101101011001101001
    Note that it has 58 binary digits.
  2. Round the number to 53 significant binary digits:
    1100110110011111110001101010001001101111101101011001100000
    The last 58−53=5 original binary digits, 01001, started with 0 and hence have been rounded down. (This has the same effect as subtracting 01001, i.e. 9 in the decimal system, from the original number.) 
  3. Convert the number back to the decimal system. (Again, the Windows calculator can do this, but alternatively you can just add/subtract the amount by which the original number has been rounded up/down, see item 2: ...1801−9=...1792.)
    231512182813021792

The 53 bits mentioned in item 2 are the so called "implied bit" plus the 52 mantissa bits which SAS stores internally besides the 1+11 bits for the sign and exponent, respectively (see Numerical Accuracy in SAS Software [linked by yabwon already] for more details).

 

To avoid the loss of precision, you should store integers of this size in character variables, as Kurt Bremser has recommended. Using PROC DS2 or PROC FedSQL you can still handle them (up to certain limits, see BIGINT data type) as numeric values: see the old thread Convert large number for an example. Certain calculations can even be done digit by digit in a DATA step (example: Mod function with big number).

SAS Innovate 2025: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!

Submit your idea!

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
  • 7 replies
  • 1899 views
  • 11 likes
  • 4 in conversation