home *** CD-ROM | disk | FTP | other *** search
-
- { 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.