On 2013-05-19 09:40, Uwe Oswald wrote:
Hi @ll,
has someone ever tried to extract fields SMF30DDS and SMF30DDR (long floating
point hex) or any field in REXX? There are a couple of F2"something" routines
out there but it seems that none of them produce the right value. Has
somebody a REXX example for me? Anything would be very appreciated since it
might bring me further.
This code coming from Michel Castelein & Jim Connelly might be of some use
/* REXX - convert float to dec + dec to float routines */
"ispclear"
do until opt = 0 | opt = ''
say 'Select option'
say
say ' 0: exit'
say ' 1: Castelein, float(hex) to dec'
say ' 2: Connelly, dec (char) to float(hex) to dec'
pull opt
opt = left(opt, 1)
select
when opt = 1 then call castelein
when opt = 2 then call connelly
otherwise
end
end
exit 0
/* This REXX exec computes a S/370 floating-point's value ...
e.g. X'C1280000' represents -2.5
(Michel Castelein, 5 November 1997)*/
castelein:
say 'Enter the S/370 floating-point (4, 8, or 16 bytes):'
numeric digits 34
pull float
float = X2C(float) /* convert float to a hexadecimal string*/
float_size = LENGTH(float) /* size in Bytes*/
Byte_0 = SUBSTR(float, 1, 1)
select
when BITAND(Byte_0, '80'x) == '00'x then sign = '+'
when BITAND(Byte_0, '80'x) == '80'x then sign = '-'
end
exponent = C2D(BITAND(Byte_0, '7F'x)) - 64
fraction = 0
power = -1
do i = 2 to float_size
if i = 9 then iterate /* skip bits 64-71*/
Next_Byte = C2D(SUBSTR(float, i, 1))
left_Digit = Next_Byte % 16
fraction = fraction + left_Digit * 16**power
right_Digit = Next_Byte // 16
power = power - 1
fraction = fraction + right_Digit * 16**power
power = power - 1
end
interpret 'value =' sign ( fraction * 16 ** exponent )
say "The floating-point's value is" value
say
say 'Press Enter to continue'
pull
return
/*
TEST_WORK.FS=1.00000E+01;
TEST_WORK.FL=1.000000000000000E+01;
TEST_WORK.FE=1.00000000000000000000000000000000E+01;
'41A00000'B
'41A0000000000000'B
'41A00000000000003300000000000000'B
TEST_WORK.FS=3.16227E+00;
3.16227722167968750000
TEST_WORK.FL=3.162277660168379E+00;
3.162277660168379300742458326567430049181
TEST_WORK.FE=3.16227766016837933199889354443270E+00;
3.162277660168379331998893544432716995013
'413298B0'B
'413298B075B4B6A5'B
'413298B075B4B6A533240945790619B3'B
*/
/*------------ REXX -----------------------------+
* |
* Converts a number to internal float format. |
* Displays the result |
* Then converts the result back out to decimal. |
* |
* Written by Jim Connelley |
* |
* Tracing thru this code is a good way to get |
* familiar with IBM system 390 internal |
* floating point format. |
* |
*-----------------------------------------------+
*/
connelly:
Numeric Digits 100 /* handle BIG numbers */
/*
Parse Upper Arg input_val .
*/
say 'Enter S/390 floating point value'
pull input_val .
Say "Input Value: " input_val
If datatype(input_val) /= "NUM" Then Do
Say "invalid value"
return
End
If input_val = 0 Then Do /* special case zero */
Say "Resulting Value: 0000000000000000"
Say "Floating value converted back: 0"
return
End
input_val = Format(input_val)
/*-------------------------------------------------------+
* Handle leading minus sign |
*-------------------------------------------------------+
*/
If left(input_val,1) = "-" Then Do
Sign = "80"x
input_val = Substr(input_val,2) /* remove sign */
End
Else Do
Sign = "00"x
End
/*-------------------------------------------------------+
* Separate input into integer and fraction |
*-------------------------------------------------------+
*/
Parse Var input_val input_integer "." input_fract
/*-------------------------------------------------------+
* If no fraction given, then default to zero |
*-------------------------------------------------------+
*/
If input_fract = "" Then input_fract = 0
input_fract = "."input_fract
/*-------------------------------------------------------+
* Convert integer portion directly |
*-------------------------------------------------------+
*/
float_value = D2x(input_integer)
If float_value = "0" Then float_value = ""
/*-------------------------------------------------------+
* If there is no integer portion, then we can normalize |
* just the fraction portion of the input value. |
*-------------------------------------------------------+
*/
exponent = Length(float_value)
If exponent = 0 Then Do Forever
normalizing_fraction = input_fract * 16
If normalizing_fraction >= 1 Then Leave
input_fract = normalizing_fraction
exponent = exponent - 1
End
/*-------------------------------------------------------+
* compute amount to normalize |
*-------------------------------------------------------+
*/
If exponent < 0 Then Do
amount_to_normalize = 0
End
Else Do
amount_to_normalize = exponent
End
/*-------------------------------------------------------+
* Normalize the build float value. |
*-------------------------------------------------------+
*/
remainder = input_fract
Do i = 1 To (14 - amount_to_normalize)
normalizing_value = remainder * 16
quotient = normalizing_value % 1
remainder = normalizing_value // 1
float_value = float_value || D2x(quotient)
End
/*-------------------------------------------------------+
* Convert integer portion directly |
*-------------------------------------------------------+
*/
sign_and_exponent = C2x(Bitor(X2c(D2x(exponent+64)),Sign))
result_value = Substr(C2x(X2c(sign_and_exponent||float_value)),1,16)
Say "Resulting floating value: " result_value
/*-------------------------------------------------------+
* Now begin conversion back out to decimal display. |
*-------------------------------------------------------+
*/
internal_float = X2c(result_value)
/*-------------------------------------------------------+
* Extract the sign and exponent byte |
*-------------------------------------------------------+
*/
sign_and_exponent = Substr(internal_float,1,1)
/*-------------------------------------------------------+
* Compute the true exponent |
*-------------------------------------------------------+
*/
x_exponent = Bitand(sign_and_exponent,"7f"x)
excess_64_exp = C2d(x_exponent)
true_exponent = excess_64_exp - 65
/*-------------------------------------------------------+
* Create a factor of +1 or -1 from the sign bit |
*-------------------------------------------------------+
*/
sign_factor = ((Bitand(sign_and_exponent,"80"x)="00"x)-.5)*2
/*-------------------------------------------------------+
* Extract the "fraction" part of the number |
*-------------------------------------------------------+
*/
fraction = Substr(internal_float,2)
hex_fraction = C2x(fraction)
result_value = 0
/*-------------------------------------------------------+
* Sum the result value by processing each hex digit |
*-------------------------------------------------------+
*/
Do i = 1 To Length(hex_fraction)
hex_digit = X2d(Substr(hex_fraction,i,1))
result_value = result_value + (hex_digit * (16**true_exponent))
true_exponent = true_exponent - 1
End
/*-------------------------------------------------------+
* Factor in the sign |
*-------------------------------------------------------+
*/
result_value = result_value * sign_factor
/*-------------------------------------------------------+
* Format the result |
*-------------------------------------------------------+
*/
print_value = Strip(Strip(Format(result_value,,14),T,0),T,.)
If print_value = 0 Then /* Maybe we stripped too much */
print_value = Format(result_value,2,14,2,0)
Say "Floating value converted back:" print_value
say
say 'Press Enter to continue'
pull
return
--
Robert AH Prins
robert(a)prino(d)org
----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to [email protected] with the message: INFO IBM-MAIN