![]() |
Extended To String mit dekadischen Einheiten
Hallo,
da ich bei der Suche nach einer Umwandlungsfunktion, die mir einen Extended-Wert in einen String wandelt, und dabei auch die dekadischen (Tausender-) Einheiten angibt, nichts passendes gefunden habe, hier meine Funktion :
Delphi-Quellcode:
// uses MATH
function ConvertValueToString(Value : Extended; Short, Eleminate : Boolean; OutString : String; accuracy : Integer): String; Const ExportString : array[Boolean, 1..17] of String = (('Yokto', 'Zepto', 'Atto', 'Femto', 'Piko', 'Nano', 'Micro', 'Milli', '', 'Kilo', 'Mega', 'Giga', 'Terra', 'Peta', 'Exa', 'Zetta', 'Yotta'), ('y', 'z', 'a', 'f', 'p', 'n', 'µ', 'm', '', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')); var Exp : Integer; Range : Integer; ExpStep : Extended; begin ExpStep := 1 / 1000; if (accuracy < 0) or (accuracy > 18) then accuracy := 3; // set accuracy := 3 at wrong Input if Value = 0 then // Value = 0 begin Result := '0.000 '+OutString; Exit; end; if Value < 0 then Range := -1 else Range := 1; Exp := Trunc(ln(Value * Range) / ln(2) / 10+ ExpStep); if (Value >= 1E25) or ((1/Value) >= 1E25) then Result := Format('%.*f %s', [0, Value, OutString]) else if Eleminate and (Value > -1) and (Value < 1) and (Exp > -8) then Result := Format('%.*f %s%s', [accuracy, Value*1000 / Power(10, Exp * 3), ExportString[Short, Exp+8], OutString]) else Result := Format('%.*f %s%s', [accuracy, Value / Power(10, Exp * 3), ExportString[Short, Exp+9], OutString]); end; // konvertiert einen Extended-Wert in einen String // Value : Wert [Extended] // Short : True = kurze Exponententialwerte : 'K für Kilo' .... , False = Exponentialwerte ausgeschrieben // OutString : Einheit zum Anhängen an die Ausgabe // ausserhalb der Definitionen wird die Standard-Schreibweise zurückgegeben (Bereich: <1E-25 und >1E25) // accuracy : 0.. 18 NachkommaStellen // 0 wird als 0.000 und ggf. + OutString zurückgegeben // Eliminate : True = Eliminierung der führenden Null bei -1 < Wert < 1 , aus 0,123Milli... wird 123Mikro... |
Re: Extended To String mit dekadischen Einheiten
Ich würde den "OutString" einfach weglassen.
Der Benutzer der Funktion kann ja jederzeit selbst eine Einheit (oder sonstigen String) hinten anhängen. Statt 'not defined' würde ich in diesem Problemfall einfach die wissenschaftliche E-Schreibweise (z.B. 2,789E67) zurückliefern. |
Re: Extended To String mit dekadischen Einheiten
Zitat:
Zitat:
Delphi-Quellcode:
Format('%.*f %s', [accuracy, Value, S])
Zitat:
Delphi-Quellcode:
Const
ExpString : array[Boolean, 1..17] of String = (('Yokto', 'Zepto', 'Atto', 'Femto', 'Piko', 'Nano', 'Micro', 'Milli', '', 'Kilo', 'Mega', 'Giga', 'Terra', 'Peta', 'Exa', 'Zetta', 'Yotta'), ('y', 'z', 'a', 'f', 'p', 'n', 'µ', 'm', '', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')); Result := Format('%.*f %s %s', [accuracy, Value / Power(10, Exp * 3), ExpString[Short, Index], OutString]); // oder doch besser array[Boolean] of array[1..17] of String *grübel* |
Re: Extended To String mit dekadischen Einheiten
Hallo,
die überflüssige Zeile mit mit Index ... ist entfernt und die Rückgabe von 0 kann ja jeder gestalten, wie er möchte, zumal es wenig Sinn macht, 0 durch diese Funktion zu jagen. @himitsu : danke, an ein zweidimensionales array hab' ich nun gar nicht gedacht. ... warum einfach, wenn's auch schwer geht ...... :wall: |
AW: Extended To String mit dekadischen Einheiten
Moin.
eine etwas überarbeitete Version :
Delphi-Quellcode:
// Value : Wert [Extended] // Short : True = kurze Exponententialwerte : 'K für Kilo' .... , False = Exponentialwerte ausgeschrieben // OutString : Einheit zum Anhängen an die Ausgabe // Accuracy : Genauigkeit // Digits : NachkommaStellen // Eliminate : True = Eliminierung der führenden Null bei -1 < Wert < 1 , aus 0,123Milli... wird 123Mikro.. function FloatToStrS(Value : Extended; Short, Eliminate : Boolean; OutString : String; accuracy, digits : Integer): String; const ExportString : array[Boolean, 1..17] of String = ((' Yokto', ' Zepto', ' Atto', ' Femto', ' Piko', ' Nano', ' Micro', ' Milli', ' ', ' Kilo', ' Mega', ' Giga', ' Tera', ' Peta', ' Exa', ' Zetta', ' Yotta'), (' y', ' z', ' a', ' f', ' p', ' n', ' µ', ' m', ' ', ' K', ' M', ' G', ' T', ' P', ' E', ' Z', ' Y')); var Exp : Integer; Range : Integer; ExpStep : Extended; begin ExpStep := 1 / 1000; if (accuracy < 0) or (accuracy > 18) then accuracy := 3; if Value = 0 then begin Result := '0 '+OutString; Exit; end; if Value < 0 then Range := -1 else Range := 1; if ((Value > -1) and (Value < 1)) then Exp := Trunc(ln(Value * Range) / ln(2) / 10 + ExpStep) else Exp := Trunc(ln((Value*10) * Range) / ln(2) / 10 + ExpStep)+1; if (Value >= 1E25) or ((1/Value) >= 1E25) then Result := 'out of Range' else if ((Eliminate) and (Value > -1) and (Value < 1) and (Exp > -8)) then Result := FloatToStrF(Value*1000 / Power(10, Exp * 3), ffNumber, accuracy, digits) + ExportString[Short, Exp+8] + OutString else if not Eliminate then Result := FloatToStrF(Value / Power(10, Exp * 3), ffNumber, accuracy, digits) + ExportString[Short, Exp+9] + OutString else if Eliminate then Result := FloatToStrF(Value / Power(10, (Exp-1) * 3), ffNumber, accuracy, digits) + ExportString[Short, Exp+8] + OutString; end; |
AW: Extended To String mit dekadischen Einheiten
Zitat:
Zum Beispiel bei S:=FloatToStrS(1e50,False,False,'',10,5); gibt deine Funktion 100.000000 m zurück. Und: "Terra" sollte "Tera" heißen, und die korrekte Kurzform für "Kilo" ist "k", nicht "K" |
AW: Extended To String mit dekadischen Einheiten
Zitat:
Das erste
Delphi-Quellcode:
kann weg, denn der Code kommt immer beim letzten
Result := '0' + ' ' + OutString;
Delphi-Quellcode:
vorbei. (nur die Nicht-verwendet-Prüfung funktioniert bei gemanageden Typen nicht so richtig)
Result := ...
Delphi-Quellcode:
könnte auch weg, denn es ist ja schon 0, aber ich würde die Prüfung eher mit IsZero, IsSameValue oder CompareValue und einem passenden Epsilon aufbauen, falls der Fließkommawert eben mal nicht "ganz" genau 0 ist. :angle:
else Value := 0;
|
AW: Extended To String mit dekadischen Einheiten
Moin,
danke für die Anregungen, "Tera" ist geändert. Das "K" für KILO ist bewusst groß geschrieben, da sich mittlerweile dies im Allgemeinen als Schreibweise durchgesetzt hat, wer mag, kann dies ja ändern. ... über eine sinnvolle Prüfung / Behandlung von Werten außerhalb des Arbeitsbereiches werd' ich heute Abend mal nachgrübeln :gruebel: |
AW: Extended To String mit dekadischen Einheiten
Zitat:
Funktion benutze ich in Programmen (z.B. beim Vergleich von errechneten Widerstandswerten mit der E-96- bzw. E192-Reihe), wo ich dann auch einen entsprechenden Epsilon-Wert definiere, verschieden für z.B. die E-96-Reihe und E-192-Reihe. |
AW: Extended To String mit dekadischen Einheiten
Teilweise weichen die Bezeichner etwas ab.
z.B. km und KB Aus diesem Grund würde ich für jeden Kontext einen Record verwenden, der den Wert selber speichert und mit einer
Delphi-Quellcode:
Methode diesen Friendly-String ausgibt. Dann hat man exakt das, was man haben will und genau da wo man es braucht.
ToString
Der Quellcode liest sich dann auch viel einfacher:
Delphi-Quellcode:
function CalculateResistance( const U: TVoltage; const I: TCurrent ): TResistance;
begin Result := I.Value / U.Value; end; WriteLn( CalculateResistance( 24, 4 ).ToString() ); |
AW: Extended To String mit dekadischen Einheiten
Ersmal: Nicht Extended verwenden, sondern Double.
Im Grunde was Extended nicht für die Verwendung vorgesehen, sondern "nur" für die internen Berechnungen der FPU. In 64 Bit gibt es Extended daher auch nicht mehr. (der Delphi-Compiler verwendet an der Stelle "heimlich" Double) Extended kann bis zu 4951 Nachkommastellen haben und Double auch immernoch 324. Wenn es nicht genau 0 wird, dann die kann Schleife viel öfters durchlaufen, als gewollt. |
AW: Extended To String mit dekadischen Einheiten
Zitat:
. . . überarbeitet |
AW: Extended To String mit dekadischen Einheiten
Und bitte übernimm nicht den Tippfehler von himitsu. Es heißt Epsilon und nicht Expsilon. :roll:
|
AW: Extended To String mit dekadischen Einheiten
ups :shock:
|
AW: Extended To String mit dekadischen Einheiten
Neee, das ist doch kein Fehler ... war nur von Expstep geguttenbergt. :oops:
|
AW: Extended To String mit dekadischen Einheiten
Zunächst: Danke für die Funktion! Habe gerade genau nach so etwas gesucht.
Ist die aktuellste Version im Beitrag #5? Wenn ja, dann ist dort Tera immer noch falsch geschrieben. Zudem sollte es vermutlich Eliminate statt Eleminate heißen (wenn damit "eliminieren" gemeint ist). Meine eigentliche Frage bezieht sich jedoch auf die Anzahl der Vorkommastellen. Ist hierfür Accuracy vorgesehen? Wie kann ich denn festlegen, dass ab 4 Vorkommastellen in die nächste Einheit gewechselt werden soll?
Delphi-Quellcode:
liefert "1E3 M"
FloatToStrS(1000000000, True, True, '', 3, 0)
Delphi-Quellcode:
liefert "1.000 M"
FloatToStrS(1000000000, True, True, '', 4, 0)
Wie komme ich denn zu "1 G"? |
AW: Extended To String mit dekadischen Einheiten
|
AW: Extended To String mit dekadischen Einheiten
Zitat:
|
AW: Extended To String mit dekadischen Einheiten
Zitat:
FloatToStrS(1000000000, False, False, 6, 0) sollte 1 G ergeben. |
AW: Extended To String mit dekadischen Einheiten
Sorry, aber irgendwie passt das nicht. Ist jetzt noch falscher als vorher.
Zum Testen:
Delphi-Quellcode:
Erwartete Ausgabe:
for i := 0 to 9 do
begin Number := Power(10, i); s := s + FloatToStrS(Number, False, False, '', 3, 0) + #13#10; end; ShowMessage(s);
Code:
Alte Version:
1
10 100 1 Kilo 10 Kilo 100 Kilo 1 Mega 10 Mega 100 Mega 1 Giga
Code:
Neue Version:
1
10 100 1E3 10 Kilo 100 Kilo 1E3 Kilo 10 Mega 100 Mega 1E3 Mega
Code:
0 Kilo
0 Kilo 0 Kilo 1 Kilo 0 Mega 0 Mega 1 Mega 0 Giga 0 Giga 1 Giga |
AW: Extended To String mit dekadischen Einheiten
Liste der Anhänge anzeigen (Anzahl: 2)
@ CodeX
Du musst die Anzahl der Digits schon hoch setzen, sonst erwischt Du nur die 1000er ! siehe Screenshot ... oder Eliminate verwenden - siehe Screenshot 2 |
AW: Extended To String mit dekadischen Einheiten
Naja, Sinn ist es doch, dass ich einfach eine Zahl übergebe und diese mit einer optimalen Formatierung erhalte, ohne mir Gedanken zu machen, wie viele Stellen die Zahl hat bzw. ohne weitere Parameter anzupassen.
Dein zweiter Screenshot zeigt das Problem doch auch: Warum sind es 1.000 Mega und nicht 1 Giga? Sobald die nächst größere Einheit mit Zahl vor dem Komma erreicht ist, sollte doch auch in diese gewechselt werden. Das wäre wie gesagt die gewünschte Ausgabe:
Code:
1 10 100 1 Kilo ! 10 Kilo 100 Kilo 1 Mega ! 10 Mega 100 Mega 1 Giga ! |
AW: Extended To String mit dekadischen Einheiten
was soll den die optimale Formatierung sein ?
Diese ist in jedem Fall erst mal von der Verwendung abhängig, z.B. beim Messen elektrischer Größen benötige ich bei einer Bauteilangebe von : Toleranz = ±0,02 % mind. 4 Nachkommastellen, um dieses Bauteil beurteilen zu können. Woher soll die Funktion wissen, wie viele Nachkomastellen - oder Vorkommastellen ich haben möchte ? o.k. an dem Wechsel zu den 1000er-Stellen muss ich noch mal nachschauen, die Anzahl der Vor- oder Nachkommastellen soll jedenfalls weiterhin mit übergeben werden. |
AW: Extended To String mit dekadischen Einheiten
Zitat:
Delphi-Quellcode:
eine Formatierung herauskommen, die ab 4 Vorkommastellen in die nächste Einheit wechselt und keine Nachkommastellen hat. Stattdessen kommt sowas wie "1E3 Mega" raus. Das halte ich für falsch. Da sollte in dem Fall "1 Giga" stehen.
FloatToStrS(Zahl, True, True, '', 3, 0)
Nochmal: Statt "1E3 Mega" oder "1000 Mega" sollte "1 Giga" herauskommen. Gleiches natürlich für die anderen Einheiten. |
AW: Extended To String mit dekadischen Einheiten
Liste der Anhänge anzeigen (Anzahl: 1)
@ CodeX
... so sollte es gehen, ist bestimmt noch verbesserbar, liefert aber erstmal das gewünschte Ergebnis. Post # 5 aktualisiert |
AW: Extended To String mit dekadischen Einheiten
Jetzt passt es, danke! :thumb:
|
AW: Extended To String mit dekadischen Einheiten
Ich möchte ja nicht wieder "meckern", aber es funktioniert wohl doch noch nicht richtig. Bei runden Zahlen klappt das (wie in Deinem Screenshot zu sehen), aber ab 102 kommt nur Quatsch:
Delphi-Quellcode:
for i := 0 to 2000 do
Memo1.Lines.Add(IntToStr(i) +': '+ FloatToStrS(i, True, True, '', 3, 0));
Code:
99: 99
100: 100 101: 101 102: 0 K 103: 0 K ... 498: 0 K 499: 0 K 500: 1 K 501: 1 K ... 1498: 1 K 1499: 1 K 1500: 2 K 1501: 2 K |
AW: Extended To String mit dekadischen Einheiten
Keine Idee?
|
AW: Extended To String mit dekadischen Einheiten
Zitat:
dann bekommst Du bei einem Ausgangswert von 498 ----> 0,498 K. Wenn dagegen die Anzahl der Nachkommastellen auf 0 steht, kann da nichts Vernünftiges bei 'raus kommen. |
AW: Extended To String mit dekadischen Einheiten
Zitat:
Du willst doch nicht sagen, dass es so gewollt ist: 101 -> 101 102 -> 0 K Was macht es für einen Sinn, dass 102-499 in 0 K umgewandelt werden, und 500-999 in 1 K? Es sind nur 3 Stellen, daher brauchen sie ja nicht in die nächsthöhere Einheit umgewandelt werden. Erst bei 1000 - 1999 müsste es 1 K sein (bei 0 Nachkommastellen). |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:15 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 by Thomas Breitkreuz