'=========================================================================== ' Subject: PASCAL REAL TO QBASIC DOUBLE Date: 02-24-97 (00:00) ' Author: Steven Edwards Code: QB, QBasic, PDS ' Origin: Charles Quante Packet: MISC.ABC '=========================================================================== 'This little routine I came up with proved to be very useful to me. I hope you think it 'would be very useful to others as well. ' ' From: Steven Edwards ' Date: 02/24/97 ' Re: Converting Pascal Random Access files REAL data types ' to QBASIC usable DOUBLE data type ' ' 'This was the original pascal data structure from the source code: ' ' EmployeeType = record ' EmpName : string[30]; ' Number : integer; ' Wage : real; ' end; {record} ' 'This Record structure was used to build a random access file. 'The Pascal string is easy to convert: ' EmployeeType.EmpName is actually 31 bytes. ' The first byte is the number of chars in the 30 that the EmpName ' actually occupies; the remaining 30 are alpha-numeric chars ' that make up the actual EmpName plus any garbage left over from ' previous strings. Use the number from the first byte to strip ' out the valid sting from the remaining 30 bytes. ' 'The Pascal real was not so easy to convert: ' The pascal real is contained in the following layout: ' ' 765432107654321076543210765432107654321076543210 <- bit structure ' |------|--------------------------------^------| ' | | ^ | ' exponent Significand ^ ' as byte as 5 bytes this is the pos/neg bit ' ' After searching long and hard for a conversion routine and not ' finding one, I set about creating my own. Using the Borland ' Pascal Language Guide and some old Turbo Pascal source code as ' a guide, I managed to convert over the information with the ' following routines. They basically do the following: ' ' 765432107654321076543210765432107654321076543210 ' |------|-------|-------|-------|-------|-------| ' byte1 byte2 byte3 byte4 byte5 byte6 <- held as string * 6 ' ' 1. Check bit 7 of byte 6 for pos/neg flag ' 2. Check each bit (0-7) of each byte (2-6) of the significand and ' multiply it out by its respective power ' (Ex.: byte 2 bit 0 is power of 1 ; byte 6 bit 7 is power of 40) ' 3. Normalize the final number (divide by 2 to the power of 40) ' 4. Calculate in the exponent (from the pascal book : * 2 to the power ' of the exponent-128) ' 5. Adjust the sign ' ' Here is a sample of the source I am using. It only calculates out for ' reading of the real number. Maybe someone with more DECLARE FUNCTION power# (x!, y AS INTEGER) DECLARE SUB RealConv (RealCost AS ANY, NewCost#) ' the QBASIC equivalent of the above Pascal struct: TYPE PASdataRecord EmpNameLength AS STRING * 1 EmpName AS STRING * 30 Number AS INTEGER Wage AS STRING * 6 END TYPE ' set up the file to be opened and read from QBASIC DIM EmployeeDAT AS PASdataRecord OPEN "EMPLOY.DAT" FOR RANDOM ACCESS READ LOCK WRITE AS #1 LEN = LEN(EmployeeDAT) ' read the file a record at a time until the end DO WHILE NOT EOF(1) CLS Count = Count + 1 SEEK #1, Count GET #1, , EmployeeDAT ' strip out the actual string using the first length byte EmployeeDAT.EmpName = MID$(EmployeeDAT.EmpName, 1, ASC(EmployeeDAT.EmpNameLength)) ' the following routine converts the pascal real to Qbasic double CALL RealConv(EmployeeDAT.Wage, BASwage#) PRINT "Employee number = "; EmployeeDAT.Number PRINT "Employee EmpName = "; EmployeeDAT.EmpName PRINT "Employee wage = "; BASwage LOOP FUNCTION power# (x, y AS INTEGER) ' simple x to the power of y function power# = EXP(y * LOG(x)) END FUNCTION SUB RealConv (Real$, NewCost#) ' create an array to hold each byte of the real string DIM RealHold(6) RealHold(1) = ASC(MID$(Real$, 1, 1)) RealHold(2) = ASC(MID$(Real$, 2, 1)) RealHold(3) = ASC(MID$(Real$, 3, 1)) RealHold(4) = ASC(MID$(Real$, 4, 1)) RealHold(5) = ASC(MID$(Real$, 5, 1)) RealHold(6) = ASC(MID$(Real$, 6, 1)) ' if positive contains a number then its negative positive = &H80 AND RealHold(6) ' clear the Pos/Neg bit from byte 6 RealHold(6) = &H80 OR RealHold(6) ' set up the significand as 1.0 Significand# = 1# ' check each individual bit for on/off; if on then multiply out the ' number (2,4,8,16,32,64,128, etc.) FOR bytecheck = 2 TO 6 ' bit 0 of byte IF (RealHold(bytecheck) AND &H1) = 1 THEN Significand# = Significand# + power(2, (0 + (bytecheck - 2) * 8)) END IF ' bit 1 of byte IF (RealHold(bytecheck) AND &H2) = 2 THEN Significand# = Significand# + power(2, (1 + (bytecheck - 2) * 8)) END IF ' bit 2 of byte IF (RealHold(bytecheck) AND &H4) = 4 THEN Significand# = Significand# + power(2, (2 + (bytecheck - 2) * 8)) END IF ' bit 3 of byte IF (RealHold(bytecheck) AND &H8) = 8 THEN Significand# = Significand# + power(2, (3 + (bytecheck - 2) * 8)) END IF ' bit 4 of byte IF (RealHold(bytecheck) AND &H10) = 16 THEN Significand# = Significand# + power(2, (4 + (bytecheck - 2) * 8)) END IF ' bit 5 of byte IF (RealHold(bytecheck) AND &H20) = 32 THEN Significand# = Significand# + power(2, (5 + (bytecheck - 2) * 8)) END IF ' bit 6 of byte IF (RealHold(bytecheck) AND &H40) = 64 THEN Significand# = Significand# + power(2, (6 + (bytecheck - 2) * 8)) END IF ' bit 7 of byte IF (RealHold(bytecheck) AND &H80) = 128 THEN Significand# = Significand# + power(2, (7 + (bytecheck - 2) * 8)) END IF NEXT ' normalize the number by dividing calculated number by a number with all ' bits turned on: 2 to the power of 40 Significand# = Significand# / power(2, 40) ' calculate in the exponent Number# = Significand# * power(2, (RealHold(1) - 128)) ' set the pos/neg sign IF positive > 0 THEN Number# = Number# * -1 NewCost# = Number# END SUB