![]() |
Extended in bruch umformen
Hi
Ich kann es ehrlich gesagt kaum glauben, das es zu diesem Thema noch keine wirkliche Lösung gibt... das einzige was ich finden konnte war folgendes:
Delphi-Quellcode:
Von
procedure DezToBruch(DezimalZahl:double;var Zaehler,Nenner:integer;Tiefe:integer);
const ZuKlein=1E-6; Winzig=1E-12; var GanzAnteil,a,b:integer; begin GanzAnteil:=trunc(DezimalZahl+Winzig); if (Tiefe>1) and (abs(DezimalZahl-GanzAnteil)>ZuKlein) then begin DezToBruch(1/(DezimalZahl-GanzAnteil),a,b,Tiefe-1); Zaehler:=a*GanzAnteil+b; Nenner:=a; end else begin Zaehler:=GanzAnteil; Nenner:=1; end; end; ![]() Aber wenn man beispielsweise -0.1 reintut, kommt -1/9 raus :( gibt es irgendwo eine komplett funktionierende Lösung? |
Re: Extended in bruch umformen
Das funktioniert auch nicht, zumindestens nicht ohne eine Library wie mein DECMath ;)
Verdeutliche dir doch mal folgendes 1 * 2^10000, als Extended benötigt man dafür eine 48 Bit große Manitsse die binär 1 einhält und als Exponenten einen maximal 15 Bit großen Wert der 10000 binär enthält. Nun wandele diese Zahl in einen Bruch um ! Es entsteht 1 * 2^10000 / 1 ergo eine Binärzahl aus einer führenden 1 mit 10000 Nullen dran. Diese große Zahl, eg. Bruch kann nur mit einer math. Library die solch großen Zahlen fassen kann dargestellt werden. Und in fact, in meinem DECMath gibt den Datentyp IRational -> ergo rationale Brüche, die einen Extendend aufnehmen können und diesen dann intern als Bruch darstellen.
Delphi-Quellcode:
Intern wird der Extended sehr simpel umgewandelt.
var
R: IRational; begin NSet(R, 1 / 3); WriteLn('R: ', NStr(R) ); WriteLn('F: ', NFloat(R) ); WriteLn('N: ', NStr(R.N) ); WriteLn('D: ', NStr(R.D) ); end; // ergibt als Ausgabe R: 0,333333333333333333333333333333333333333333333333333333 F: 0,3333333 N: 1 D: 3 Man extrahiert dazu die Mantisse als 48 Bit Binärzahl und den Exponenten zur Basis 2 ebenfalls als Binärzahl. Je nach Vorzeichen des Exponenten ist die Zahl kleiner 1.0 oder größer.
Delphi-Quellcode:
Entscheidend ist die sogenannte Normalization eines Bruches, d.h. aus 4/6 den kleinesten eindeutigen Bruch von 2/3 zu finden.
procedure NSet(var A: IRational; const B: Extended);
type ExtRec = packed record Man: array[0..1] of Cardinal; Exp: Word; end; var I: Integer; begin NSet(A, 0); if B <> 0 then with NAlloc(A)^ do begin if ExtRec(B).Exp and $7FFF = $7FFF then begin // B >= 1.0 NSet(FN, B); NNormalize(A); end else begin // B < 1.0 I := (ExtRec(B).Exp and $7FFF) - $3FFE - 64; NSet(FN, ExtRec(B).Man, 8); NNeg(FN, B < 0); if I > 0 then NShl(A, I) else if I < 0 then NShr(A, -I) else NNormalize(A); end; end; end; R = N//D T = GCD(N, D) R' = (N/T) // (D/T) // Bruchstrich. Wie man sieht muß man den größten gemeinsammen Teiler vom Nominator N und Denominator D per GCD() finden. Dieser Wert T wird dann 1 oder größer 1 sein. Gruß hagen |
Re: Extended in bruch umformen
Hmm...irgendwo hatte ich diesen Teil der DEC mal gesehen bei mir auf der Platte....aber ich finde ihn nicht mehr :(
Gibt es eine neue Version für D2005 oder soll ich den aus dem Thread hier in der DP nehmen? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:27 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz