![]() |
Delphi-Version: 10.3 Rio
Case-Statement für Float-Werte
Hallo,
ich habe gerade ein simples Case-Statement mit Single-Werten geschrieben. Leider kann ich es nicht kompilieren. Die Meldung lautet: Zitat:
So habe ich es versucht:
Delphi-Quellcode:
TibZoomFactorPercent = (
Custom, Percent10, Percent25, Percent50, Percent75, Percent100, Percent125, Percent150, Percent175, Percent200, Percent250, Percent300, Percent400, Percent500 ); function TfrmEditor.GetZoomFactorAsPercent( AZoomFactor: Single = 1): TibZoomFactorPercent; begin Result := TibZoomFactorPercent.Custom; case AZoomFactor of // Hier tritt der Fehler auf... 0.10: Result := TibZoomFactorPercent.Percent10; 0.25: Result := TibZoomFactorPercent.Percent25; 0.50: Result := TibZoomFactorPercent.Percent50; 0.75: Result := TibZoomFactorPercent.Percent75; 1: Result := TibZoomFactorPercent.Percent100; 1.25: Result := TibZoomFactorPercent.Percent125; 1.50: Result := TibZoomFactorPercent.Percent150; 1.75: Result := TibZoomFactorPercent.Percent175; 2: Result := TibZoomFactorPercent.Percent200; 2.50: Result := TibZoomFactorPercent.Percent250; 3: Result := TibZoomFactorPercent.Percent300; 4: Result := TibZoomFactorPercent.Percent400; 5: Result := TibZoomFactorPercent.Percent500; end; end; |
AW: Case-Statement für Float-Werte
Was spricht dagegen das du nur mit ganzen Prozentwerten arbeitest.
Damit hast du einen Integer und kannst wieder mit case-Statement arbeiten. |
AW: Case-Statement für Float-Werte
Moin...:P
Zitat:
|
AW: Case-Statement für Float-Werte
Zitat:
Gleitkommazahlen sind nun mal mathematisch keine Ordinalen. Sherlock |
AW: Case-Statement für Float-Werte
Dazu lässt sich 0.10 auch gar nicht exakt als Single darstellen.
|
AW: Case-Statement für Float-Werte
Zitat:
|
AW: Case-Statement für Float-Werte
Entweder
Delphi-Quellcode:
oder
Round(AZoomFactor * 100)
mehrere if´s in dieser Form:
Delphi-Quellcode:
Im Grunde ist die zweite Variante noch übersichtlicher.
function TfrmEditor.GetZoomFactorAsPercent(
AZoomFactor: Single = 1): TibZoomFactorPercent; begin Result := TibZoomFactorPercent.Custom; if (AZoomFactor = 0.10) then Exit(TibZoomFactorPercent.Percent10); if (AZoomFactor = 0.25) then Exit(TibZoomFactorPercent.Percent25); ... end; Sie ist etwas aufwendiger zu tippen, aber das ist ja ein einmaliger Aufwand. Man ist auch etwas freier in der Ausgestaltung. Zu beachten ist, dass Floatwerte immer Ungenauigkeiten beinhalten können. Deshalb sollte man ggf. eine Funktion wie SameValue zum Vergleich verwenden. |
AW: Case-Statement für Float-Werte
|
AW: Case-Statement für Float-Werte
Danke für eure vielen Antworten. Das ich mit ganzen Prozenten oder mit If-Abfragen das Problem lösen kann war mir von Anfang an klar. Ich wollte nur wissen warum es nicht möglich ist Float-Werte in einem Case-Statement zu verwenden. Ebenso Strings. Liegt das "nur" am Daten-Typ oder wurde es einfach nicht im Compiler implementiert? Ich hatte mal einen PreCompiler (ich glaube es war IDE Fix Pack oder so ähnlich) mit dem man u. a. Strings in Case verwenden konnte. Das war vor über 10 Jahren... Warum baut Embarcadero sowas nicht mal ein? Floats, Strings, etc. Ich finde das wäre ein tolles Feature...
|
AW: Case-Statement für Float-Werte
Ja, ich fände das auch gut.
Es würde sich ja lediglich um eine andere Schreibweise von if-Statements handeln. Der Compiler könnte quasi identischen Maschinencode wie bei if-Statements erzeugen. Schwieriger wäre sicherlich, das auch dem Debugger beizubringen. Wie hoch der Aufwand letztlich in Summe wäre, kann ich nicht wirklich beurteilen. |
AW: Case-Statement für Float-Werte
Zitat:
Leider ist es bei Delphi wie so oft ein ![]() |
AW: Case-Statement für Float-Werte
@Andreas L.:
Vielleicht ließe sich Dein Vorhaben auch wie folgt realisieren: 1: Die AZoomFactor-Werte von Single in einen String mit nur 3 Ziffern umwandeln 2: Dann würde die Fallunterscheidung für Strings mittels
Delphi-Quellcode:
funktionieren. Ein Beispiel hierfür findest Du hier:
Case AnsiIndexText(..)
![]() Andreas |
AW: Case-Statement für Float-Werte
Weil CASE im Delphi nur mit ordinalen Typen arbeitet, also Integer/Byte/Char/..., und das intern oft mathematisch (mit Addition/Substraktion) optimiert wird.
|
AW: Case-Statement für Float-Werte
Zitat:
Delphi-Quellcode:
Alles mit "Wert = 0.10" KANN nicht funktionieren, also genausowenig mit case,
function TfrmEditor.GetZoomFactorAsPercent(
AZoomFactor: Single = 1): TibZoomFactorPercent; begin Result := TibZoomFactorPercent.Custom; case Trunc(AZoomFactor * 100) of // Hier tritt der Fehler auf... 10: Result := TibZoomFactorPercent.Percent10; 25: Result := TibZoomFactorPercent.Percent25; 50: Result := TibZoomFactorPercent.Percent50; 75: Result := TibZoomFactorPercent.Percent75; 100: Result := TibZoomFactorPercent.Percent100; 125: Result := TibZoomFactorPercent.Percent125; 150: Result := TibZoomFactorPercent.Percent150; 175: Result := TibZoomFactorPercent.Percent175; 200: Result := TibZoomFactorPercent.Percent200; 250: Result := TibZoomFactorPercent.Percent250; 300: Result := TibZoomFactorPercent.Percent300; 400: Result := TibZoomFactorPercent.Percent400; 500: Result := TibZoomFactorPercent.Percent500; end; weil man float Werte nicht einfach vergleichen kann. (Siehe unten die Vorschläge mit SameValue) Deshalb wird es ein case mit float nicht geben können. |
AW: Case-Statement für Float-Werte
Um den Grund an sich noch mal auf den Punkt zu bringen:
CASE und IF sind nur funktional miteinander verwandt. CASE war ursprünglich mehr als nur eine andere (kürzere) Schreibart für eine Kette von IF-Statements, da es dem Compiler hier einfacher war effizienteren Maschinencode daraus zu generieren. Einschränkung: Da dafür Sprungtabellen (bestehend aus relativen Adressen, die halt immer ganzzahlig sind) aus den zu unterscheidenden Werten gebildet wurden/werden, waren/sind nur solche als Kriterium zulässig. In Zeiten, in denen jeder einzelne Prozessorzylus noch in vielfachen (Dollar-)Cents zu bemessen war, war das eine lukrative Angelegenheit. Und auch heute noch sind solche "kleinkarierten" Optimierungen hier und da noch messbare Vorteile - jedoch werden diese immer seltener, und das Argument der einfacheren Schreib-/Lesbarkeit ist in den Vordergrund gerückt. Welcher Seite man als Compiler-Hersteller nun die Stange hält, ist meiner Meinung nach weitestgehend Geschmackssache. Delphi hat die Optimierbarkeit beibehalten, und somit die Beschränkung auf Ordinaltypen. Will man das nicht, muss man mit diesem Compiler etwas tricksen um die Lesbarkeit zu erhalten, oder einen anderen wählen und die Optimierbarkeit aufgeben. |
AW: Case-Statement für Float-Werte
Es gäbe aber keinen Grund Beides nicht zu kombinieren.
Wenn der CASE-Wert Ordinal ist, dann den optimierten Code generieren, und ansonsten könnte der Compilier das notfalls auch als viele IF-ElseIf-ElseIf-...-Else umsetzen, bzw. für Strings in ein CASE mit IndexStr/IndexText übersetzen usw. Denn wenn wir versuchen das Vorhaben so zu optimieren, damit es ins CASE passt, dann kommt weniger lesbarer Code bei raus, als wenn das der Compilier intern anpassen würde. Genauso wie es echt saudoof ist, dass IN immernoch als grauenhaftes SET-Assembler übersetzt wird, anstatt es optional mit BitMasken oder InArray umzusetzen. Oder dass CharInSet intern nur Mist macht und man den Dreck nicht wieder entfernt, weil IN durch ein IN in einer Funktion zu ersetzen, welche einfach nur die CompilerWarnung unterdrückt, dass ist sowas von schwachsinnig nutzlos. Wobei das CharInSet-Problem sofort behoben ist, wenn man für "IN WideChar" die grade erwähnte Verbesserung hätte, oder einfach die selbe Codeoptimierug verwenden würde, wie aktuell beim CASE. |
AW: Case-Statement für Float-Werte
Zitat:
Das sollte immer schneller sein als sequentielles IF. Falls du Recht hast das dies nicht schneller ist würde es doch bedeuten das der Compiler das IF intern doch als Sprungtabelle optimiert, oder nicht ? Schneller wäre vielleicht nur ein Auslagern in Prozeduren-Pointer, als einfache State-Machine statt CASE oder IF, aber auch das bezweifele ich wenn im case nur wenig gemacht wird. Da kann der Compiler doch perfekt optimieren (wenn er das könnte). Die Sprungtebellen der CPU sollten doch das effektivste Mittel bleiben, oder habe ich da was verpasst ? (Ich habe aber die letzten Jahre intensives CPU-Technologie Studium geschwänzt, Hauptsache das Ding läuft :stupid:) |
AW: Case-Statement für Float-Werte
Zitat:
Edit: Um das klar zu stellen: Ich sage nicht, dass case schlechter lesbar ist als if-Kaskaden. Aber ein "auf deubel komm raus" Klimmzug um mit eigentlich nicht passenden Typen es dennoch irgendwie in ein case zu pressen verliert definitiv zumindest an Wartbarkeit, da man Umwege einführt die man ggf. als Dritter nicht erwartet, und jede zusätzliche Zeile Code wieder eine mögliche Fehlerquelle mehr ist. |
AW: Case-Statement für Float-Werte
Es gibt ja keinen Grund nicht beides haben zu können. Wenn es ein Ordinalwert ist macht der Compiler alles wie bisher. Wenns kein Ordinalwert ist, wirds intern eben wie ein verschachteltes if-else behandelt.
|
AW: Case-Statement für Float-Werte
Zitat:
|
AW: Case-Statement für Float-Werte
Ich bin ganz froh, dass es nicht geht mit String u.a. in cases. Da werde ich oder die Kollegen darauf gestossen, dass der Code den sie schreiben vorhaben, schlecht ist. (Meistens weil man dann SoC) verletzt.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:41 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