157 lines
4.8 KiB
Plaintext
157 lines
4.8 KiB
Plaintext
|
||
{ Copyright (c) 1985, 87 by Borland International, Inc. }
|
||
|
||
unit BCD;
|
||
|
||
{ The BCD version of Turbo Pascal 3.0 (TURBOBCD.COM) supports
|
||
10-byte binary coded decimal reals with 18 significant digits
|
||
and a range of 1E-63 to 1E+63. The BCD real data type is not
|
||
supported by Turbo Pascal 4.0, and this unit provides a routine
|
||
for converting 3.0 BCD reals to 6-byte reals (software reals)
|
||
or 10-byte 8087 extended reals.
|
||
|
||
Before you convert a Turbo Pascal 3.0 BCD program to run under
|
||
4.0, you need to select a 4.0 real data type for your floating
|
||
point values. If you do not have an 8087, or if your program is
|
||
to run on machines without an 8087, your only option is to use
|
||
the familiar 6-byte Real, which provides 11-12 significant digits
|
||
with a range of 2.9E-39 to 1.7E+38. This type is also supported by
|
||
the standard version of Turbo Pascal 3.0. If you are planning to
|
||
use the 8087, we suggest you select the 10-byte Extended type,
|
||
which provides 19-20 significant digits with a range of 1.9E-4951
|
||
to 1.1E+4932. Once you have selected a data type, you need to write
|
||
a conversion program that translates your old data files using the
|
||
conversion routine provided here.
|
||
|
||
The Decimal type defined by this unit corresponds to the 3.0 BCD
|
||
Real, and the DecToFloat routine converts a Decimal variable to a
|
||
6-byte Real or to a 10-byte Extended.
|
||
|
||
The BCD unit uses conditional compilation constructs to define a
|
||
type Float which is equivalent to either Real or Extended,
|
||
depending on the kind of numeric processing you select (software
|
||
or hardware). To compile a program that uses the BCD unit, first
|
||
select software or hardware floating point, using the Options/
|
||
Compiler/Numeric processing menu, and then do a Compile/Build,
|
||
which automatically recompiles BCD.PAS.
|
||
|
||
The following program shows how to convert a 3.0 data file that
|
||
contains records with BCD fields. The program defines an equivalent
|
||
of the 3.0 record (OldDataRec) using the Decimal type for fields
|
||
that contain BCD reals. In the corresponding 4.0 record (NewDataRec),
|
||
floating point fields are declared using the Float type, which is
|
||
either Real or Extended depending on the floating point model
|
||
selected. During the conversion, all Decimal fields are converted
|
||
to Float using the DecToFloat function, whereas all non-real fields
|
||
are copied directly.
|
||
|
||
program ConvertBCD;
|
||
uses BCD;
|
||
type
|
||
OldDataRec = record
|
||
Name: string[15];
|
||
InPrice,OutPrice: Decimal;
|
||
InStock,MinStock: Integer;
|
||
end;
|
||
NewDataRec = record
|
||
Name: string[15];
|
||
InPrice,OutPrice: Float;
|
||
InStock,MinStock: Integer;
|
||
end;
|
||
var
|
||
OldFile: file of OldDataRec;
|
||
NewFile: file of NewDataRec;
|
||
Old: OldDataRec;
|
||
New: NewDataRec;
|
||
begin
|
||
Assign(OldFile,'OLDFILE.DTA'); Reset(F);
|
||
Assign(NewFile,'NEWFILE.DTA'); Rewrite(F);
|
||
while not Eof(OldFile) do
|
||
begin
|
||
Read(OldFile,Old);
|
||
New.Name := Old.Name;
|
||
New.InPrice := DecToFloat(Old.InPrice);
|
||
New.OutPrice := DecToFloat(Old.OutPrice);
|
||
New.InStock := Old.InStock;
|
||
New.MinStock := Old.MinStock;
|
||
Write(NewFile,New);
|
||
end;
|
||
Close(OldFile);
|
||
Close(NewFile);
|
||
end.
|
||
|
||
The range of a BCD real is larger than that of a 6-byte software
|
||
real. Therefore, when converting to 6-byte reals, BCD values larger
|
||
than 1E+38 are converted to 1E+38, and BCD values less than 2.9E-39
|
||
are converted to zero.
|
||
}
|
||
|
||
interface
|
||
|
||
type
|
||
Decimal = array[0..9] of Byte;
|
||
{$IFOPT N-}
|
||
Float = Real;
|
||
{$ELSE}
|
||
Float = Extended;
|
||
{$ENDIF}
|
||
|
||
function DecToFloat(var D: Decimal): Float;
|
||
|
||
implementation
|
||
|
||
function DecToFloat(var D: Decimal): Float;
|
||
var
|
||
E,L,P: Integer;
|
||
V: Float;
|
||
|
||
function Power10(E: Integer): Float;
|
||
var
|
||
I: Integer;
|
||
P: Float;
|
||
begin
|
||
I:=0; P:=1.0;
|
||
repeat
|
||
if Odd(E) then
|
||
case I of
|
||
0: P:=P*1E1;
|
||
1: P:=P*1E2;
|
||
2: P:=P*1E4;
|
||
3: P:=P*1E8;
|
||
4: P:=P*1E16;
|
||
5: P:=P*1E32;
|
||
end;
|
||
E:=E shr 1; Inc(I);
|
||
until E=0;
|
||
Power10:=P;
|
||
end;
|
||
|
||
begin
|
||
{$IFOPT N-}
|
||
if D[0] and $7F>38+$3F then V:=10E37 else
|
||
{$ENDIF}
|
||
begin
|
||
V:=0.0; L:=1;
|
||
while (L<=9) and (D[L]=0) do Inc(L);
|
||
if L<=9 then
|
||
begin
|
||
for P:=9 downto L do
|
||
begin
|
||
V:=V*100.0+((D[P] shr 4)*10+D[P] and $0F);
|
||
end;
|
||
E:=D[0] and $7F-($3F+(10-L)*2);
|
||
if E>=0 then V:=V*Power10(E) else
|
||
begin
|
||
if E<-32 then
|
||
begin
|
||
V:=V/1E32; E:=E+32;
|
||
end;
|
||
V:=V/Power10(-E);
|
||
end;
|
||
end;
|
||
end;
|
||
if D[0] and $80=0 then DecToFloat:=V else DecToFloat:=-V;
|
||
end;
|
||
|
||
end.
|
||
|