home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / turbo5 / turbo3 / bcd.pas next >
Pascal/Delphi Source File  |  1988-10-09  |  5KB  |  157 lines

  1.  
  2. { Copyright (c) 1985, 88 by Borland International, Inc. }
  3.  
  4. unit BCD;
  5.  
  6. { Die BCD-Version von Turbo Pascal 3.0 (TURBOBCD.COM) unterstützt
  7.   binär codierte Dezimalzahlen mit 18 signifikanten Stellen und einem
  8.   Rechenbereich von 1E-63 bis 1E+63, die jeweils 10 Bytes Speicherplatz
  9.   belegen.
  10.   Der Datentyp BCD ist in der Version 4.0 nicht definiert - deshalb enthält
  11.   dieses Unit eine Routine, die BCD-Werte der Version 3.0 entweder in
  12.   Werte des Typs Real (mit jeweils 6 Bytes) oder in Werte des Typs Extended
  13.   (mit jeweils 10 Bytes) konvertiert. 
  14.  
  15.   Vor der Konvertierung eines 3.0-BCD-Programms sollten Sie den zukünftig
  16.   verwendeten Datentyp festlegen. Wenn Ihr Computer nicht mit einem 8087
  17.   ausgerüstet ist oder das Programm grundsätzlich auf Computern ohne 8087 
  18.   verwendet werden soll, empfehlen sich Variablen des Typs Real (6 Bytes, 
  19.   11-12 Dezimalstellen Genauigkeit, Bereich 2.9E-39..1.7E+38). Dieser Typ 
  20.   wird auch von der Standard-Version des 3.0-Compilers unterstützt.
  21.   Wenn Sie über einen 8087 verfügen, sollten sie den Typ Extended anstelle
  22.   von BCD verwenden, der 10 Bytes belegt, 19-20 Dezimalstellen Genauigkeit
  23.   und einen Rechenbereich von 1.9E-4951..1.1E+4932 bietet.
  24.   Nach der Konvertierung des Programms sollten Sie ein weiteres Programm zur
  25.   Konvertierung existierender Dateien schreiben, das die in diesem Unit
  26.   deklarierte Routine zur Umsetzung verwendet.
  27.  
  28.   Der hier deklarierte Typ Decimal entspricht den BCD-Variablen der Version
  29.   3.0; die Routine DecToFloat konvertiert eine derartige Variable - je nach
  30.   Stand des Compiler-Schalters $N - in das Format Real bzw. Extended.
  31.  
  32.   Um ein Programm zu compilieren, das das Unit BCD benutzt, setzen Sie zuerst
  33.   den Schalter $N (mit O/C/Numeric processing) entsprechend (für Real: auf
  34.   "Software", für Extended: auf "8087-80287") und rufen den Compiler dann
  35.   über C/Build auf. Dadurch wird auch das Unit BCD neu compiliert.
  36.  
  37.  
  38.   Das folgende Programmbeispiel zeigt die Konvertierung einer 3.0-Datei,
  39.   deren Records einzelne BCD-Felder enthalten:
  40.     - Definition eines Äquivalents des 3.0-Records (OldDataRec) unter
  41.       Verwendung des Pseudo-Typs Decimal
  42.     - Definition eines 4.0-Records, desssen entsprechende Felder als
  43.       Typ Float deklariert sind. Float steht je nach Stand des Schalters
  44.       $N entweder für den Typ Real oder den Typ Extended.
  45.     - Während der Umsetzung werden alle Felder mit BCD-Werten über DecToFloat
  46.       konvertiert -- die restlichen Felder der Records werden dagegen direkt
  47.       in die neue Datei kopiert.
  48.  
  49.   program ConvertBCD;  (* Dieses Beispielprogramm ist Teil eines Kommentars *)
  50.   uses BCD;
  51.   type
  52.     OldDataRec = record
  53.                    Name: string[15];
  54.                    InPrice,OutPrice: Decimal;
  55.                    InStock,MinStock: Integer;
  56.                  end;
  57.     NewDataRec = record
  58.                    Name: string[15];
  59.                    InPrice,OutPrice: Float;
  60.                    InStock,MinStock: Integer;
  61.                  end;
  62.   var
  63.     OldFile: file of OldDataRec;
  64.     NewFile: file of NewDataRec;
  65.     Old: OldDataRec;
  66.     New: NewDataRec;
  67.   begin
  68.     Assign(OldFile,'OLDFILE.DTA'); Reset(F);
  69.     Assign(NewFile,'NEWFILE.DTA'); Rewrite(F);
  70.     while not Eof(OldFile) do
  71.     begin
  72.       Read(OldFile,Old);
  73.       New.Name     := Old.Name;
  74.       New.InPrice  := DecToFloat(Old.InPrice);
  75.       New.OutPrice := DecToFloat(Old.OutPrice);
  76.       New.InStock  := Old.InStock;
  77.       New.MinStock := Old.MinStock;
  78.       Write(NewFile,New);
  79.     end;
  80.     Close(OldFile);
  81.     Close(NewFile);
  82.   end.
  83.  
  84.   Der Rechenbereich einer BCD-Realvariablen ist größer als der des Typs
  85.   Real: DecToFloat begrenzt deshalb Werte > 1.0E+38 auf 1.0E+38; Werte kleiner
  86.   2.9E-39 werden als 0 konvertiert.
  87. }
  88.  
  89. interface
  90.  
  91. type
  92.   Decimal = array[0..9] of Byte;
  93. {$IFOPT N-  O/C/Numeric processing..Software?}
  94.   Float = Real;    { -> ja, Datentyp Real }
  95. {$ELSE}
  96.   Float = Extended;
  97. {$ENDIF}
  98.  
  99. function DecToFloat(var D: Decimal): Float;
  100.  
  101. implementation
  102.  
  103. function DecToFloat(var D: Decimal): Float;
  104. var
  105.   E,L,P: Integer;
  106.   V: Float;
  107.  
  108. function Power10(E: Integer): Float;
  109. var
  110.   I: Integer;
  111.   P: Float;
  112. begin
  113.   I:=0; P:=1.0;
  114.   repeat
  115.     if Odd(E) then
  116.     case I of
  117.       0: P:=P*1E1;
  118.       1: P:=P*1E2;
  119.       2: P:=P*1E4;
  120.       3: P:=P*1E8;
  121.       4: P:=P*1E16;
  122.       5: P:=P*1E32;
  123.     end;
  124.     E:=E shr 1; Inc(I);
  125.   until E=0;
  126.   Power10:=P;
  127. end;
  128.  
  129. begin
  130. {$IFOPT N-}
  131.   if D[0] and $7F>38+$3F then V:=10E37 else
  132. {$ENDIF}
  133.   begin
  134.     V:=0.0; L:=1;
  135.     while (L<=9) and (D[L]=0) do Inc(L);
  136.     if L<=9 then
  137.     begin
  138.       for P:=9 downto L do
  139.       begin
  140.         V:=V*100.0+((D[P] shr 4)*10+D[P] and $0F);
  141.       end;
  142.       E:=D[0] and $7F-($3F+(10-L)*2);
  143.       if E>=0 then V:=V*Power10(E) else
  144.       begin
  145.         if E<-32 then
  146.         begin
  147.           V:=V/1E32; E:=E+32;
  148.         end;
  149.         V:=V/Power10(-E);
  150.       end;
  151.     end;
  152.   end;
  153.   if D[0] and $80=0 then DecToFloat:=V else DecToFloat:=-V;
  154. end;
  155.  
  156. end.
  157.