Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations MikeeOK on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Converting Pascal Real's to Numeric

Status
Not open for further replies.

wgcs

Programmer
Mar 31, 2002
2,056
EC
I've been trying to adapt faq184-1932 Float64ToNum to work with the 48 bit Pascal Real data type.

So far, I've been unsuccessful...

Here's a description of the difference:

Here's my code so far:
Code:
LPARAMETERS Float48 AS STRING

* Pascal Real:
***  S MMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM EEEEEEEE
*    1 2345678 90123456 78901234 56789012 34567890 12345678
*               1          2          3          4

* 64 bit float:
*!*        S XXXXXXX XXXX MMMM MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM
*!*        0 0000000 0000 0000 00000000 00000000 00000000 00000000 00000000 00000000
*!*        1 2345678 9012 3456 78901234
*!*                   1           2         3

LOCAL SIGN AS INTEGER
LOCAL Bias AS INTEGER
LOCAL Exponent AS INTEGER
LOCAL I AS INTEGER
LOCAL x AS STRING
LOCAL Mantissa AS NUMBER
LOCAL OldDecimals AS INTEGER
LOCAL oldFixed AS STRING
IF LEN(Float48) < 6
  RETURN 0
ENDIF
*OldDecimals=SET(&quot;Decimals&quot;)
*SET DECIMALS TO 20
oldFixed=SET(&quot;Fixed&quot;)
SET FIXED OFF
Mantissa = 1
SIGN     = 0
Bias     = 129 && 64bit bias: 1023
Exponent = 0
Float48  = LEFT(Float48,6)

SIGN=IIF(BITTEST(ASC(LEFT(Float48,1)),7),-1,1)

FOR I=48 TO 41 STEP -1
  Exponent=Exponent+IIF(BITTEST(ASC(SUBSTR(Float48,INT((I-1)/8)+1,1)),7-MOD((I-1),8)),1,0) * (2^(47-I))
*  Exponent=Exponent+IIF(BITTEST(ASC(SUBSTR(Float64,INT((I-1)/8)+1,1)),7-MOD((I-1),8)),1,0)*(2^(12-I))
NEXT
Exponent=Exponent-bias

FOR I=2 TO 40
  AA=INT((I-1)/8)+1
  BB=7-MOD((I-1),8)
  B=IIF(BITTEST(ASC(SUBSTR(Float48,INT((I-1)/8)+1,1)),7-MOD((I-1),8)),1,0)
  Mantissa=Mantissa+IIF(BITTEST(ASC( SUBSTR(Float48,INT((I-1)/8)+1,1)), 7-MOD((I-1),8)),1,0) * (1/(2^(I-1)))
*  Mantissa=Mantissa+IIF(BITTEST(ASC(SUBSTR(Float64,INT((I-1)/8)+1,1)),7-MOD((I-1),8)),1,0)*(1/(2^(I-12)))
NEXT
SET FIXED &oldFixed
RETURN SIGN*(Mantissa)*(2^Exponent)
ENDFUNC
Any help would be appreciated!
 
BTW: Here are some sample Real's to test with (generated by a Borland Pascal v7 program):

Literal value = ASCII char values representing a Pascal Real
Code:
1   = 129 0 0 0 0 0 
2   = 130 0 0 0 0 0 
10  = 132 0 0 0 0 32 
20  = 133 0 0 0 0 32 
100 = 135 0 0 0 0 72 
200 = 136 0 0 0 0 72 
0.1 = 125 205 204 204 204 76 
0.01= 122 113  61  10 215 35 
1.1 = 129 205 204 204 204 12
 
Ok, I got it: It took me a while to realize that, finally, my conversion was correct, but that pascal was writing the real to the file 'backwards' (ie byte #6 comes first).

So, here's the working code:
Code:
* info from: [URL unfurl="true"]http://docs.sun.com/db/doc/801-5055/6hvhckkeh?a=view[/URL]
*            [URL unfurl="true"]http://info.borland.com/techpubs/delphi/delphi5/oplg/memory.html[/URL]
*            [URL unfurl="true"]http://www.tek-tips.com/faqs.cfm?spid=184&sfid=1932[/URL]
*              faq184-1932
* A 6-byte (48-bit) Real48 number is divided into three fields:
*
*   1 bit: Sign
*  39 bits: f (mantissa)
*   8 bits: e (exponent)
*  If 0 < e <= 255, the value v of the number is given by 
*     v = (-1)^s * 2^(e-129) * (1.f ) 
*  If e = 0, then v = 0. 

LPARAMETERS Float48 AS STRING

* Pascal Real:
***  S MMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM EEEEEEEE
*    1 2345678 90123456 78901234 56789012 34567890 12345678
*               1          2          3          4

* 64 bit float:
*!*        S XXXXXXX XXXX MMMM MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM
*!*        0 0000000 0000 0000 00000000 00000000 00000000 00000000 00000000 00000000
*!*        1 2345678 9012 3456 78901234
*!*                   1           2         3

LOCAL SIGN AS INTEGER
LOCAL Bias AS INTEGER
LOCAL Exponent AS INTEGER
LOCAL I AS INTEGER
LOCAL x AS STRING
LOCAL Mantissa AS NUMBER
LOCAL OldDecimals AS INTEGER
LOCAL oldFixed AS STRING
IF LEN(Float48) < 6
  RETURN 0
ENDIF
*OldDecimals=SET(&quot;Decimals&quot;)
*SET DECIMALS TO 20
oldFixed=SET(&quot;Fixed&quot;)
SET FIXED OFF
Mantissa = 1
SIGN     = 0
Bias     = 129 && 64bit bias: 1023
Exponent = 0
Float48  = LEFT(Float48,6)

SIGN=IIF( BITTEST(ASC(Float48),7), -1, 1)

FOR I=48 TO 41 STEP -1
*FOR I=12 TO 2 STEP -1
  AA = INT((I-1)/8)+1  && Find the appropriate Byte to look in
  BB = 7-MOD((I-1),8)  && Find the appropriate bit in that byte
  B = BITTEST(ASC(SUBSTR(Float48,AA,1)),BB)      && Find out if that bit is set
  
  Exponent=Exponent+IIF( B, 2^(48-I), 0) 
                        
*  Exponent=Exponent+IIF(BITTEST(ASC(SUBSTR(Float64,INT((I-1)/8)+1,1)),7-MOD((I-1),8)),1,0)*(2^(12-I))
NEXT
Exponent=Exponent-bias

FOR I=2 TO 40
*FOR I=13 TO 64
  AA = INT((I-1)/8)+1  && Find the appropriate Byte to look in
  BB = 7-MOD((I-1),8)  && Find the appropriate bit in that byte
  B = BITTEST(ASC(SUBSTR(Float48,AA,1)),BB)      && Find out if that bit is set
  Mantissa = Mantissa + IIF( B, 1/(2^(I-1)), 0 ) && If set, add to the total Mantissa
  
*  Mantissa=Mantissa+IIF(BITTEST(ASC(SUBSTR(Float64,INT((I-1)/8)+1,1)),7-MOD((I-1),8)),1,0)*(1/(2^(I-12)))
NEXT
SET FIXED &oldFixed
RETURN SIGN*(Mantissa)*(2^Exponent)
ENDFUNC
 
The FAQ (I don't know who wrote it... user name: 738262) was invaluable... but it was really frustrating when the info from converting the char's to the pieces of the Float just didn't make sense! I think I now have a handle on the math behind it, and everything just came clear when I realized the Real numbers were stored in reverse-byte-order.

Sometimes you just need a wall to bounce Ideas off of.... [dazed]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top