- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Hi @arunrami,
Here are the details of what SAS did to your numeric literal 231512182813021801 (assuming a Windows or Unix operating system):
- 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. - 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.) - 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).
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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 ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
@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 😉
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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 😞
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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:
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Hi @arunrami,
Here are the details of what SAS did to your numeric literal 231512182813021801 (assuming a Windows or Unix operating system):
- 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. - 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.) - 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).
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Thanks @FreelanceReinh , @FreelanceReinh and @yabwon .