home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turbo Toolbox
/
Turbo_Toolbox.iso
/
turbo4
/
bcdreal.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1987-12-08
|
5KB
|
156 lines
{ Copyright (c) 1985, 87 by Borland International, Inc. }
unit BCDReal;
{ Die BCD-Version von Turbo Pascal 3.0 (TURBOBCD.COM) unterstützt
binär codierte Dezimalzahlen mit 18 signifikanten Stellen und einem
Rechenbereich von 1E-63 bis 1E+63, die jeweils 10 Bytes Speicherplatz
belegen.
Der Datentyp BCD ist in der Version 4.0 nicht definiert - deshalb enthält
dieses Unit eine Routine, die BCD-Werte der Version 3.0 entweder in
Werte des Typs Real (mit jeweils 6 Bytes) oder in Werte des Typs Extended
(mit jeweils 10 Bytes) konvertiert. Für die Konvertierung in den Typ
Extended wird ein numerischer Coprozessor (8087) vorausgesetzt.
Vor der Konvertierung eines 3.0-BCD-Programms sollten Sie den zukünftig
verwendeten Datentyp festlegen. Wenn Ihr Computer nicht mit einem 8087
ausgerüstet ist oder das Programm auf Computern ohne 8087 verwendet
werden soll, müssen Sie Variablen des Typs Real (6 Bytes, 11-12 Dezimal-
stellen Genauigkeit, Bereich 2.9E-39..1.7E+38) verwenden. Dieser Typ wird
auch von der Standard-Version des 3.0-Compilers unterstützt.
Wenn Sie über einen 8087 verfügen, sollten sie den Typ Extended anstelle
von BCD verwenden, der 10 Bytes belegt, 19-20 Dezimalstellen Genauigkeit
und einen Rechenbereich von 1.9E-4951..1.1E+4932 bietet.
Nach der Konvertierung des Programms sollten Sie ein weiteres Programm zur
Konvertierung existierender Dateien schreiben, das die in diesem Unit
deklarierte Routine zur Umsetzung verwendet.
Der hier deklarierte Typ Decimal entspricht den BCD-Variablen der Version
3.0; die Routine DecToFloat konvertiert eine derartige Variable - je nach
Stand des Compiler-Schalters $N - in das Format Real bzw. Extended.
Um ein Programm zu compilieren, das das Unit BCD benutzt, setzen Sie zuerst
den Schalter $N (mit O/C/Numeric processing) entsprechend (für Real: auf
"Software", für Extended: auf "Hardware") und rufen den Compiler dann
über C/Build auf. Dadurch wird auch das Unit BCD neu compiliert.
Das folgende Programmbeispiel zeigt die Konvertierung einer 3.0-Datei,
deren Records einzelne BCD-Felder enthalten:
- Definition eines Äquivalents des 3.0-Records (OldDataRec) unter
Verwendung des Pseudo-Typs Decimal
- Definition eines 4.0-Records, desssen entsprechende Felder als
Typ Float deklariert sind. Float steht je nach Stand des Schalters
$N entweder für den Typ Real oder den Typ Extended.
- Während der Umsetzung werden alle Felder mit BCD-Werten über DecToFloat
konvertiert -- die restlichen Felder der Records werden dagegen direkt
in die neue Datei kopiert.
program ConvertBCD; (* Dieses Beispielprogramm ist Teil eines Kommentars *)
uses BCDReal;
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.
Der Rechenbereich einer BCD-Realvariablen ist größer als der des Typs
Real: DecToFloat begrenzt deshalb Werte > 1.0E+38 auf 1.0E+38; Werte kleiner
2.9E-39 werden als 0 konvertiert.
}
interface
type
Decimal = array[0..9] of Byte;
{$IFOPT N-}
Float = Real; { kein Coprozessor }
{$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 V:=V/1E32; E:=E+32;
V:=V/Power10(-E);
end;
end;
end;
if D[0] and $80=0 then DecToFloat:=V
else DecToFloat:=-V;
end;
end.