home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turbo Toolbox
/
Turbo_Toolbox.iso
/
turbo5
/
turbo3
/
bcd.pas
next >
Wrap
Pascal/Delphi Source File
|
1988-10-09
|
5KB
|
157 lines
{ Copyright (c) 1985, 88 by Borland International, Inc. }
unit BCD;
{ 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.
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 grundsätzlich auf Computern ohne 8087
verwendet werden soll, empfehlen sich Variablen des Typs Real (6 Bytes,
11-12 Dezimalstellen Genauigkeit, Bereich 2.9E-39..1.7E+38). 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 "8087-80287") 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 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.
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- O/C/Numeric processing..Software?}
Float = Real; { -> ja, Datentyp 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.