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

Hello!

I am utilizing the following code to convert numeric values to character values.

  array valsc (*) $ vsbpsysc vsbpdiac vspulsec vsrespc;

  array vals (*) vsbpsys vsbpdia vspulse vsresp;

  array norm (*) $ tempnorm bpnorm hrnorm respnorm;

  do i =1 to dim(valsc);

       valsc{i}=strip(put(vals{i},8.));

       if strip(norm{i}) = '' then do;

            valsc{i}=strip(norm{i});

       end;

  end;

I run the code and get no syntax errors, however the values of the array valsc come up as blank values.

When I do each variable individually, ie vsbpsysc=put(vsbpsys ,8.); I get the result I am looking for.


This makes me wonder, is what I am attempting to do possible with arrays (since the elements of the two different arrays are of different types)?




EDIT: I found out what I was doing incorrectly. I had a type-o in my code, it should have read:

if strip(norm{i})^ = '' then do;

            valsc{i}=strip(norm{i});

       end;

1 ACCEPTED SOLUTION

Accepted Solutions
RW9
Diamond | Level 26 RW9
Diamond | Level 26

You have mixed up what has values and what doesn't there. 

data have;

  vsbpsys=12; vsbpdia=13; vspulse=20; vsresp=5;

run;

data want;

  set have;

  array valsc (*) $20. vsbpsysc vsbpdiac vspulsec vsrespc;

  array vals (*) 8. vsbpsys vsbpdia vspulse vsresp;

  do i =1 to dim(valsc);

    valsc{i}=strip(put(vals{i},8.));

  end;

run;

So, I have the numeric values to start with, and they get converted to character.  (also put the full format with length on it as well).

View solution in original post

15 REPLIES 15
RW9
Diamond | Level 26 RW9
Diamond | Level 26

You have mixed up what has values and what doesn't there. 

data have;

  vsbpsys=12; vsbpdia=13; vspulse=20; vsresp=5;

run;

data want;

  set have;

  array valsc (*) $20. vsbpsysc vsbpdiac vspulsec vsrespc;

  array vals (*) 8. vsbpsys vsbpdia vspulse vsresp;

  do i =1 to dim(valsc);

    valsc{i}=strip(put(vals{i},8.));

  end;

run;

So, I have the numeric values to start with, and they get converted to character.  (also put the full format with length on it as well).

ChrisNZ
Tourmaline | Level 20

The cats function is the best and easier way to do this conversion these days:

    valsc{i}=cat( vals{i} );

data t;

  array a [2] (-.00000000001234567890123456 -1234567890123456 );

  b1=put(a[1],32.26);  b2=put(a[2],32.);    put b1= @35 b2= ;

  b1=put(a[1],best32.);b2=put(a[2],best32.);put b1= @35 b2= ;

  b1=cat(a[1]);        b2=cat(a[2]);        put b1= @35 b2= ;

run;

b1=-0.00000000001234567890123450  b2=-1234567890123456

b1=-1.2345678901234E-11           b2=-1234567890123456

b1=-1.2345678901234E-11           b2=-1234567890123456

Note that decimal numbers always lose precision for some reason.

I have my sixteen digits for integers (since they are < 9,007,199,254,740,992)

but only 14 ( functions cat() and format best. )  or 15 (format w.d)  for decimals


Message was edited by: Christian Graffeuille

RW9
Diamond | Level 26 RW9
Diamond | Level 26

Is it not the purpose of the put and input functions to convert data from numeric to character and vice versa using an Explicitly present format?  Personally I am quite against letting procedures guess what I want the data to look like. 

ChrisNZ
Tourmaline | Level 20

It is but most users never get it right. And cat does just as good a job without having to provide the length or number of decimals: easier and less room for errors.

data_null__
Jade | Level 19

There is no guessing

If item is numeric, then its value is converted to a character string by using the BESTw. format. In this case, leading blanks are removed and SAS does not write a note to the log.


If you want to convert to character using an associated format look to the VVALUE VVALUEX functions.

ChrisNZ
Tourmaline | Level 20

I never use format best. since it doesn't do as requested/expected.

data t;

*1; X=-0.00000000001234567890123456; Y=put(X,32.30  ); put '1- 32.30     ' Y ;

*2; X=-0.00000000001234567890123456; Y=put(X,best.  ); put '2- best.     ' Y ;

*3; X= 0.00000000001234567890123456; Y=put(X,best.  ); put '2- best.     ' Y ;

*4; X=-0.00000000001234567890123456; Y=put(X,best20.); put '4- best20.   ' Y ;

*5; X= 0.00000000001234567890123456; Y=put(X,best20.); put '5- best20.   ' Y ;

*6; X=-0.00000000001234567890123456; Y=put(X,best32.); put '6- best32.   ' Y ;

*7; X=-0.00000000001234567890123456; Y=put(X,best32.); put '7- best32.30 ' Y ;

*8; X=-1234567890123456000000000000; Y=put(X,32.30  ); put '8- 32.30     ' Y ;

run;

Yields:

1- 32.30    -.000000000012345678901234560000

2- best.     -1.23457E-11

2- best.           1.234568E-11

4- best20.   -1.2345678901235E-11

5- best20.       1.2345678901234E-11

6- best32.   -1.2345678901234E-11

7- best32.30 -1.2345678901234E-11

8- 32.30     -1234567890123456163050684416.00


Line 1: Format 32.30 displays all the wanted digits, as requested by the length of 32.

Line 2-3: Format best. drops many digits as its default length is 12. Let's accept this is a design decision.

Line 4-5: Format best20. does what's on the tin for negative numbers (but rounding is wrong), but does not use the full length for positive numbers.

Line 6-7: Format best32. does not display the requested precision, It behaves as format best20.

Line 8 : Format 32.30 doesn't correctly writes large integers but is still the "best" format here.

data_null__
Jade | Level 19

I sure I don't understand your point.  In one thread you say that CAT is the "best" way to convert numeric to character and in another you say "I never use BEST format".

As for rounding with W.D format "everyone" knows that it doesn't always round as expected as shown in this example.

data _null_;
  
x = -1e-12;
   y = round(x,
10**-6);
   put x=10.6 x= y=10.6 y=;
   run;

x=-0.000000 x=-1E-12 y=0.000000 y=0
ChrisNZ
Tourmaline | Level 20

1- I am saying cat() is good enough, precise enough, fast and easy.

    If I need full control then w.d is the best.

    Format best. the worst, cat() matches or bests any best. format.

data t;

*1; X=-0.00000000001234567890123456; Y=put(X,32.30  ); put '1- 32.30     ' Y ;

*2; X=-0.00000000001234567890123456; Y=put(X,best.  ); put '2- best.     ' Y ;

*3; X= 0.00000000001234567890123456; Y=put(X,best.  ); put '2- best.     ' Y ;

*4; X=-0.00000000001234567890123456; Y=put(X,best20.); put '4- best20.   ' Y ;

*5; X= 0.00000000001234567890123456; Y=put(X,best20.); put '5- best20.   ' Y ;

*6; X=-0.00000000001234567890123456; Y=put(X,best32.); put '6- best32.   ' Y ;

*7; X=-0.00000000001234567890123456; Y=put(X,best32.); put '7- best32.30 ' Y ;

*8; X=-1234567890123456000000000000; Y=put(X,32.30  ); put '8- 32.30     ' Y ;

*9; X=-0.00000000001234567890123456; Y=cat(X); put '9- cat()     ' Y ;

*10; X=-1234567890123456000000000000; Y=cat(X); put '10- cat()    ' Y ;

run;

1- 32.30     -.000000000012345678901234560000
2- best.     -1.23457E-11
2- best.     1.234568E-11

4- best20.   -1.2345678901235E-11

5- best20.    1.2345678901234E-11

6- best32.   -1.2345678901234E-11

7- best32.30 -1.2345678901234E-11

8- 32.30    -1234567890123456025611730944.00
9- cat()    -1.2345678901234E-11
10- cat()   -1234567890123456025611730944

2- I don't understand what you are trying to show.

I am just showing that

4- best20.   -1.2345678901235E-11

is wrong. The right value for this string length would be

4- best20.   -1.2345678901234E-11

which is what the other formatted strings contain.

Anyway to each their own...

data_null__
Jade | Level 19

1) You need read the documentation; CAT uses BEST so there is no difference.  CAT does quietly convert to character with no annoying conversion note.

2) I was saying that rounding cannot always left to w.d as it gets it wrong sometimes as shown by my example where w.d displays negative zero.

ChrisNZ
Tourmaline | Level 20

CAT uses BEST32., not BEST.

Shorter BEST. formats (which everydody uses) can yield surprises as I've shown.

So *my opinion* is : why bother, cat is easier to use and to teach, so that's what I do now.

That's the only point I have been making, and I made this point as I think it has value for less experienced SAS users.

Feel free to disagree. I've said all I had to say on this matter.  Smiley Happy

RW9
Diamond | Level 26 RW9
Diamond | Level 26

Hi,

Yes, disagree slightly here.  The use of cat would then be hiding and additional conversion part behind the scenes.  New users need to understand how data is stored and how to properly convert one type to the other, including lengths and associated truncation.  Its a bit like proc import/export, these functions work, and behind the scenes try to guess what you want to do.  Hence the constant stream of questions on here asking why x column is doing this, and why y file is not importing etc.  If they learnt how to import a file by hand typing everything in, setting formats/informats/lengths, and also how to design transfer specifications, then these questions would not arise as they would understand the principals.  Most specifications I have seen state lengths of numeric variables including how many decimal places, so as long as you follow spec then there shouldn't be any problems. 

Mind you, I suppose you could take that argument right back to why we are not programming in assembly, but hey, just trying to reduce the numbers of questions.

ChrisNZ
Tourmaline | Level 20

It depends on the crowd. A good proportion of the people I work with are not programmers. They mostly use just SQL and they always forget how to convert types. That's probably the #1 question they keep asking. Or used to be.

I wrote a to_number() function à la oracle for them for the same reason.

But I use cat() too: why bother with put(NUM, best32. -l) when it doesn't do a better job than cats (NUM)?

Sadly, we're moving onto EG soon though, so I suppose they'll like it better (we'll see how EG converts types) while the more confirmed SAS users will have to endure EG's interface (I know I know, many people here like EG for some reason I cannot fathom). SAS Studio will ease the pain somewhat.

RW9
Diamond | Level 26 RW9
Diamond | Level 26

"people I work with are not programmers" - I wouldn't let them do programming then (SQL is programming).  You wouldn't want me doing surgery would you?  Yes, tools like EG and VA are plasters, hide the code underneath so anyone can use them.  Sounds great, but in the UK at least there is a problem with people no longer understanding coding, just point an click.  Another example is tv's.  My partners nephew the other day was trying to press the tv screen, had grown up with ipad's so just didn't understand how things worked outside touch screens.

ChrisNZ
Tourmaline | Level 20

They are analysts, so they need to manipulate data. SQL is one step up from excel, and allows them to go to oracle as well. Full SAS programmation is another step up which only some climb. I feel your pain about users not always understanding what's happening ebhind the scene. Same about some "statisticians" ' models. EG was a curse in this respect, a double edged sword: more SAS users on one hand, more naive users on the other. EG should never had replaced the DMS. A good IDE should have replaced it: 2 crowds, 2 interfaces. Sadly SAS pushed EG like there's no tomorrow.

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 15 replies
  • 4291 views
  • 1 like
  • 4 in conversation