dos_compilers/Borland Turbo Pascal v4/BCD.PAS
2024-07-01 21:08:56 -07:00

157 lines
4.8 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{ 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.