if und UND-verknüpfte Bedignungen

Gast #4770401
Lesenswert?

Hallo zusammen!

Was ist denn besser? Eine Latte von UND-verknüpften Bedingungen -die 
auch Rückgabewerte von Funktionsaufrufen beinhalten-, in einer 
if-Abfrage und lieber ineinander mit aufsteigender Komplexität 
verschachtelt, um Rechenzeit zu sparen?

Danke & Grüße
Blub
Gast #4770452
Lesenswert?

Stefan P. schrieb:
> Kannst Du ruhig hintereinander schreiben. Da von links nach rechts
> abgearbeitet wird, und bei dem ersten false eh abgebrochen wird.
> Um Rechenzeit zu sparen am besten die Bedingungen die am
> häufigsten/schnellsten false liefern ganz nach links schreiben.

Super! Danke! Die Antwort, die ich gebraucht und erhofft habe! ;-)
(Firma: Torrox.de) #4771231
Lesenswert?

Blub schrieb:

> Was ist denn besser?

Übrigens kann man auch das Ergebnis von boolschen Operatoren in einer 
Variablen zwischenspeichern, wenn das ggf. die Lesbarkeit erhöht.
1
  bool first_parameter_valid  = p1 >= 4 && p1 < 20;
2
  bool second_parameter_valid = p2 >= 3 && p2 < 99;
3

4
  if ( first_parameter_valid && second_parameter_valid )
5
    ...

mfg Torsten
Gast #4771563
Lesenswert?

Torsten R. schrieb:
> Übrigens kann man auch das Ergebnis von boolschen Operatoren in einer
> Variablen zwischenspeichern, wenn das ggf. die Lesbarkeit erhöht.
1
>   bool first_parameter_valid  = p1 >= 4 && p1 < 20;
2
>   bool second_parameter_valid = p2 >= 3 && p2 < 99;
3
> 
4
>   if ( first_parameter_valid && second_parameter_valid )
5
>     ...

das erhöht aber kaum die Lesbarkeit gegenüber
1
    if( (p1>=4 && p1<20) && (p2>=3 && p2<99) )
2
        ...

Dann lieber an den Rangeprüfungen arbeiten:
1
    if(   inrange(p1, 4, 19) 
2
       && inrange(p2, 3, 98)
3
      )
4
        ...
Gast #4771960
Lesenswert?

lesbarer wird es noch in C++ mit Classen und Templates
1
#include "Range.hpp"
2
Range<int> LimitP1(4,19);
3
Range<int> LimitP2(3,98);
4

5

6

7
.
8
.
9
.
10
if (LimitP1.InRange(p1) && LimitP2.InRange(p2))
11
{
12
   ...
13
}

lesbarer wäre noch (pseudo code)
1
if (p1.InRange(LimitP1) && p2.InRange(LimitP2))
Gast #4772023
Lesenswert?

Torsten R. schrieb:
> Achim, das war nur ein Beispiel! ;-)

Das verstehe ich, Torsten, und mit Deinem Beispiel bist Du konform zu 
Lehrbüchern für guten Code. Vor allem, wenn man McCabe und anderen 
Metriken folgt, ebenso TTD (Unittests), und vorwiegend orthogonale, 
unabhängige Modulen von je ~1000 Zeilen programmiert.

Sobald man größere Projekte hat, mit Modulen von mehrern 1000 Zeilen und 
einer durch die reale Welt intensiven faktische Verknüpfung, dann rückt 
ein Problem in den Vordergund: Die Lesbarkeit (Geschwindigkeit) des 
Quellcodes. Und hier die Begrenzung von Token sowie die Anzahl der 
Indirektionsebenen.

Hier als Beispiel: Diese if-Schleife wurde durchlaufen, und jemand fragt 
sich, wieso. Wenn dort alle 100 Abfragen direkt untereinander stehen, 
kann er diese (mit dem Auge) scannen und ggf. direkt mit seiner IDE 
nähere Informatione zu p1 oder p2 bekommen. Bei first_parameter_valid 
muss er dazu erst dorthin springen.

Viele Funktionen, die Mc-Cabe senken oder Unittests vereinfachen sollen, 
erschweren real die Lesbarkeit und machen den Code (durch weggekapselten 
Kontext) unsicherer.
Moderator Persönliche Seite #4772376
Lesenswert?

Torsten R. schrieb:
> Übrigens kann man auch das Ergebnis von boolschen Operatoren in einer
> Variablen zwischenspeichern, wenn das ggf. die Lesbarkeit erhöht.

Dann fällt aber (zumindest teilweise) die genannte short-circuit
evaluation weg.  Bei deinen einfachen Variablenabfragen mag das
egal sein, aber wenn zwischendrin eine komplexere Funktion aufgerufen
wird, berechnest du ggf. ein Ergebnis, welches für die Katz' ist.

Noch schlimmer, das Ergebnis könnte undefiniert sein oder eine
Speicherschutzverletzung bringen.  Überleg' dir mal, wie du das
mit dem Zwischenspeichern in Variablen hier machst bzw. was dann
passiert:
1
   if (ptr != NULL && eval_data(ptr->data) != 42) {
2
      // …
3
   }

Danach weißt du, warum man eine wohldefinierte short-circuit
evaluation in einer Sprache braucht.  (Pascal hatte sie zumindest
im ersten Standard nicht, sondern hat es dem Compiler überlassen.
In der Folge musste man dann immer zweimal if verschachteln.)
(Firma: Torrox.de) #4772395
Lesenswert?

Jörg W. schrieb:

> Überleg' dir mal, wie du das
> mit dem Zwischenspeichern in Variablen hier machst bzw. was dann
> passiert:
>
>
1
>    if (ptr != NULL && eval_data(ptr->data) != 42) {
2
>       // …
3
>    }
4
>

Na, der "übliche" Weg ist dann, den Ausdruck schrittweise zu entwickeln:
1
const bool data_exists = ptr != 0;
2
const bool not_42      = data_exists && eval_data(ptr->data) != 42;


versteht mich nicht falsch, ich sage nicht, dass diese der einzige, 
wahre Weg ist! Ich wollte nur darauf hinweisen, dass dies ein Mittel 
sein kann, die Lesbarkeit zur erhöhen (Zitat: "wenn das ggf. die 
Lesbarkeit erhöht.")

Und ja, natürlich muss man short circuit berücksichtigen. Das muss man 
aber auch, wenn man den gesamten Ausdruck in einem hinschreibt.
(Firma: Torrox.de) #4773136
Lesenswert?

Rufus Τ. F. schrieb:
> Torsten R. schrieb:
>> const bool not_42      = data_exists && eval_data(ptr->data) != 42;
>
> Das aber setzt zwingend funktionierende short-circuit evaluation
> voraus, sonst knallt's, wenn ptr dereferenziert wird, um "eval_data"
> aufzurufen.

Oh mann, ließt den hier niemand mehr, sondern stürzt sich nur noch auf 
das letzte Posting?

Sorry, aber ich bin jetzt raus.
#4773238
Lesenswert?

Rufus Τ. F. schrieb:
> Keine Ahnung, was "leßen" sein soll - aber in einer Diskussion, wo um
> die Notwendigkeit oder nicht-Existenz der "short circuit evaluation"
> gestritten wird ... nehme ich den Thread vermutlich anders wahr als Du.

Naja, so ganz nachvollziehen kann ich den Sinn deines Postings aber auch 
nicht. Nachdem Torsten meinte, dass man
1
   if (ptr != NULL && eval_data(ptr->data) != 42) {
z.B. auch durch
1
const bool data_exists = ptr != 0;
2
const bool not_42      = data_exists && eval_data(ptr->data) != 42;
ersetzen könnte, meinst du, dass das aber zwingend short-circuit 
evaluation benötigt. Das hat aber das Original auch schon. Außerdem 
hatte er das in seinem Posting schon selber explizit erwähnt:

Torsten R. schrieb:
> Und ja, natürlich muss man short circuit berücksichtigen. Das muss man
> aber auch, wenn man den gesamten Ausdruck in einem hinschreibt.
Moderator #4773323
Lesenswert?

Dumdi D. schrieb:
> und hier das ärgerliche: beim überladenen && (in c++) gibt es wohl keine
> short-circuit evaluation.

Wozu brauchst du das? Der Short-Circuit macht ja nur dann Sinn, wenn die
Operanden wie boolesche Werte behandelt werden können. Dann kannst du
für den neuen Datentyp aber auch einfach eine Konvertierungsfunktion
nach bool (operator bool()) schreiben und die normale &&-Operation mit
Short-Circuit verwenden.

Oder nimm Haskell ;-)

Da wird defaultmäßig lazy evaluiert, was das Short-Circuiting innerhalb
einer selbstgeschriebenen Funktion automatisch nach außen trägt. Solche
Funktonen wie && und || sind dort überhaupt nichts Spezielles und auch
nicht auf boolesche Werte beschränkt.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren