2015 Jul 13 5:07 PM
This probably has been answered before, but I have not been able to find it due to me not knowing the proper term for this. My engineering users call it showing significant digits. When they say I only want to see 4 significant digits they mean the decimal point will float depending on the value of the number so that only 4 digits show. For example, if a number has the value of less than 1 the there will be 4 decimal places (.9999) if between 1 and 9 then 3 decimal places (9.999), if between 10 and 99 then 2 decimal places (99.99) etc...
1) What is this actually called,
2) Is there an existing function or static method that will do this?
3) (Bonus question) If not, how would you go about accomplishing this?
2015 Jul 13 10:43 PM
How about this?
FORM sig_digit USING | p_value |
p_digits | |
p_return. |
DATA:
intportion TYPE string, | |
numberval TYPE string, | |
declength TYPE i. |
numberval = round( val = p_value dec = p_digits ).
SHIFT numberval LEFT DELETING LEADING '0'.
SPLIT numberval AT '.' INTO intportion decportion.
IF intportion IS INITIAL.
p_return = numberval. |
ELSE.
declength = p_digits - strlen( intportion ). | |
WRITE p_value TO p_return DECIMALS declength. |
ENDIF.
shift p_return LEFT DELETING LEADING ' '.
ENDFORM.
2015 Jul 13 6:45 PM
Hi Larry,
I don't think you need any special function module to achieve this. You should be able to achieve this, using character fields.
data:significant_digits(5),
number type p decimals 10,
char_number type char20.
char_number = number = '0.99999999'.
condense char_number.
significant_digits = char_number(5).
write / significant_digits.
char_number = number = '9.99999999'.
condense char_number.
significant_digits = char_number(5).
write / significant_digits.
char_number = number = '99.9999999'.
condense char_number.
significant_digits = char_number(5).
write / significant_digits.
char_number = number = '999.999999'.
condense char_number.
significant_digits = char_number(5).
write / significant_digits.
char_number = number = '9999.99999'.
condense char_number.
significant_digits = char_number(5).
write / significant_digits.
Result:
0.999
9.999
99.99
999.9
9999.
Thanks,
Juwin
2015 Jul 13 7:10 PM
That would work, except rounding won't occur. I guess I left that part out. Also, 9999. should not have a decimal point and 0.999 should be .9999
2015 Jul 13 7:24 PM
Also, 9999. should not have a decimal point and 0.999 should be .9999
This may require specific IF conditions - because this is only related to display not specific to calculation.
Rounding can be achieved by introducing another variable in the mix, with exact number of decimal points.
data:significant_digits(5),
char_number type string,
number type p decimals 10,
rounded_number type p decimals 4.
significant_digits = char_number = rounded_number = number = '0.9998'.
write / significant_digits.
significant_digits = char_number = rounded_number = number = '9.9998'.
write / significant_digits.
significant_digits = char_number = rounded_number = number = '99.9998'.
write / significant_digits.
significant_digits = char_number = rounded_number = number = '999.9998'.
write / significant_digits.
significant_digits = char_number = rounded_number = number = '9999.9998'.
write / significant_digits.
Result:
0.999
9.999
99.99
999.9
9999.
Thanks,
Juwin
2015 Jul 13 7:53 PM
Well, this IS the problem I suppose. I am looking for some thing more generic.
This is what I had come up with but was hoping for something that would work for any number of significant digits.
FORM sig_digit4 using
num_var
char_var type char5.
Check num_var < 10000.
if num_var > 999.95.
write num_var to char_var decimals 0.
elseif num_var > 99.995.
write num_var to char_var decimals 1.
elseif num_var > 9.9995.
write num_var to char_var decimals 2.
elseif num_var > .99995.
write num_var to char_var decimals 3.
else.
write num_var to char_var decimals 4.
endif.
condense char_var.
ENDFORM.
I would need to write a separate subroutine for each different number of significant digits.
2015 Jul 13 7:59 PM
You can use dynamic variable creation techniques to make this as generic as possible.
Thanks,
Juwin
2015 Jul 13 8:10 PM
Can you try using this?
parameters:input type p decimals 10 default '0.999999',
digits type n default 4.
data:decportion type string,
intportion type string,
numberval type string,
declength type i.
numberval = round( val = input dec = digits ).
split numberval at '.' into intportion decportion.
if numberval < 1. clear intportion. endif.
declength = digits - strlen( intportion ).
if declength < 0.
write 'Err'. stop.
elseif declength = 0.
numberval = intportion.
else.
numberval = intportion && '.' && decportion(declength).
endif.
write numberval.
Thanks,
Juwin
2015 Jul 13 9:29 PM
Close, but I think it is not rounding properly. The number of rounding decimals is going to depend of the value coming in. Ex. 999.9 needs to round to 1 decimal while 99.99 needs to round to 2 decimals.
I was not aware of the "round" intrinsic?? function. What is that?
This has potential, just need to think about it a bit more.
2015 Jul 13 9:48 PM
Yep, didn't think too much about rounding. But, you get the idea now, right?
round function helps to round the value to any digits.
Thanks,
Juwin
2015 Jul 13 10:13 PM
I suppose this sort of answers my original question about a std SAP function or method to do this. It just seems like there should something to do this. I would think it is a common need for companies who do engineering work.
2015 Jul 13 10:43 PM
How about this?
FORM sig_digit USING | p_value |
p_digits | |
p_return. |
DATA:
intportion TYPE string, | |
numberval TYPE string, | |
declength TYPE i. |
numberval = round( val = p_value dec = p_digits ).
SHIFT numberval LEFT DELETING LEADING '0'.
SPLIT numberval AT '.' INTO intportion decportion.
IF intportion IS INITIAL.
p_return = numberval. |
ELSE.
declength = p_digits - strlen( intportion ). | |
WRITE p_value TO p_return DECIMALS declength. |
ENDIF.
shift p_return LEFT DELETING LEADING ' '.
ENDFORM.
2015 Jul 13 11:06 PM
Here is what I ended up with. Do you see any problems with it?
*&---------------------------------------------------------------------*
*& Form sig_digit
*&---------------------------------------------------------------------*
FORM sig_digit USING
f_value
f_digits
f_return.
DATA:
num_string TYPE string,
int_part TYPE string,
dec_part TYPE string,
declength TYPE i.
num_string = round( val = f_value dec = f_digits ).
SHIFT num_string LEFT DELETING LEADING '0'.
SPLIT num_string AT '.' INTO int_part dec_part.
declength = f_digits - strlen( int_part ).
WRITE f_value TO f_return DECIMALS declength.
SHIFT f_return LEFT DELETING LEADING ' '.
SHIFT f_return LEFT DELETING LEADING '0'.
ENDFORM. "sig_digit
2015 Jul 14 1:56 PM
2015 Jul 14 2:47 PM