AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Code-Bibliothek Neuen Beitrag zur Code-Library hinzufügen Delphi Extended To String mit dekadischen Einheiten
Thema durchsuchen
Ansicht
Themen-Optionen

Extended To String mit dekadischen Einheiten

Ein Thema von markus5766h · begonnen am 23. Jun 2009 · letzter Beitrag vom 19. Jun 2017
Antwort Antwort
Seite 1 von 3  1 23      
Benutzerbild von markus5766h
markus5766h

Registriert seit: 5. Mär 2009
Ort: Hamburg
569 Beiträge
 
Delphi XE8 Professional
 
#1

Extended To String mit dekadischen Einheiten

  Alt 23. Jun 2009, 16:53
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...
Markus H.
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#2

Re: Extended To String mit dekadischen Einheiten

  Alt 23. Jun 2009, 17:03
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.
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#3

Re: Extended To String mit dekadischen Einheiten

  Alt 23. Jun 2009, 17:06
Zitat:
Result := '0.000 '+OutString;
und was ist, wenn bei ich bei accuracy was anderes wollte, und nicht .000 ?

Zitat:
Delphi-Quellcode:
frmt := '%.'+IntToStr(accuracy)+'f %s';
Format(frmt, [Value, S])
da gibt es so ein knuffiges *
Format('%.*f %s', [accuracy, Value, S])
Zitat:
if (Value * Range) < 1 then Index := 9 + Exp else Index := Exp + 9;
9 + Exp oder Exp + 9 kommt bei mir aber auf's Gleiche raus

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*
$2B or not $2B
  Mit Zitat antworten Zitat
Benutzerbild von markus5766h
markus5766h

Registriert seit: 5. Mär 2009
Ort: Hamburg
569 Beiträge
 
Delphi XE8 Professional
 
#4

Re: Extended To String mit dekadischen Einheiten

  Alt 23. Jun 2009, 17:31
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 ......
Markus H.
  Mit Zitat antworten Zitat
Benutzerbild von markus5766h
markus5766h

Registriert seit: 5. Mär 2009
Ort: Hamburg
569 Beiträge
 
Delphi XE8 Professional
 
#5

AW: Extended To String mit dekadischen Einheiten

  Alt 20. Mär 2016, 20:54
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;
Markus H.

Geändert von markus5766h (12. Nov 2016 um 22:12 Uhr)
  Mit Zitat antworten Zitat
Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.077 Beiträge
 
Delphi XE2 Professional
 
#6

AW: Extended To String mit dekadischen Einheiten

  Alt 21. Mär 2016, 04:12
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, Eleminate : 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', 'Terra', 'Peta', 'Exa', 'Zetta', 'Yotta'),
         ('y', 'z', 'a', 'f', 'p', 'n', 'µ', 'm',
         '', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'));
var
  Exp : Integer;
  ExpStep : Extended;
begin
  Result := '0' + ' ' + OutString;
  ExpStep := 1/1000;
  Exp := 0;
  if Value <> 0 then
    begin
      Exp := Trunc(ln(Value) / ln(2) / 10 + ExpStep);
      if ((Eleminate) and (Value > -1) and (Value < 1)) then Dec(Exp, 1);
      Value := Value / Power(10, Exp * 3);
    end
      else Value := 0;
  Result := FloatToStrF(Value, ffNumber, accuracy, digits) + ' ' + ExportString[Short, Exp+9] + OutString;
end;
Was fehlt, ist die Prüfung, ob Value innerhalb des verarbeitbaren Bereiches liegt.
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"
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#7

AW: Extended To String mit dekadischen Einheiten

  Alt 21. Mär 2016, 08:44
Und: "Terra" sollte "Tera" heißen, und die korrekte Kurzform für "Kilo" ist "k", nicht "K"
Stimmt, auch wenn es etwas wiedersprüchlich ist, wo doch alle anderen "großen" Einheiten groß und die kleinen Einheiten klein geschrieben sind.


Das erste Result := '0' + ' ' + OutString; kann weg, denn der Code kommt immer beim letzten Result := ... vorbei. (nur die Nicht-verwendet-Prüfung funktioniert bei gemanageden Typen nicht so richtig)
else Value := 0; 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.
$2B or not $2B

Geändert von himitsu (22. Mär 2016 um 11:00 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von markus5766h
markus5766h

Registriert seit: 5. Mär 2009
Ort: Hamburg
569 Beiträge
 
Delphi XE8 Professional
 
#8

AW: Extended To String mit dekadischen Einheiten

  Alt 21. Mär 2016, 10:12
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
Markus H.

Geändert von markus5766h (21. Mär 2016 um 10:26 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von markus5766h
markus5766h

Registriert seit: 5. Mär 2009
Ort: Hamburg
569 Beiträge
 
Delphi XE8 Professional
 
#9

AW: Extended To String mit dekadischen Einheiten

  Alt 21. Mär 2016, 10:19
...aber ich würde die Prüfung eher mit IsZero, IsSameValue oder CompareValue und einem passenden Expsilon aufbauen, falls der Fließkommawert eben mal nicht "ganz" genau 0 ist.
Stimmt, aber dann hätte ich diese Prüfung mit passendem Epsilon in der Funktion, wo ich sie eigentlich nicht haben möchte - diese
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.
Markus H.

Geändert von markus5766h (21. Mär 2016 um 21:50 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#10

AW: Extended To String mit dekadischen Einheiten

  Alt 21. Mär 2016, 10:30
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 ToString Methode diesen Friendly-String ausgibt. Dann hat man exakt das, was man haben will und genau da wo man es braucht.

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() );
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:34 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz