Vektoren vergleich in C



  • Tergo schrieb:

    ...
    

    Nochmal übersichtlicher wird es wenn du dir angewöhnst (z.b. ab 3 Fallunterscheidungen) switch anzuwenden:

    switch( compVecLen(V1,V2) ) {
      case  0: printf("|V1| = |V2|"); break;
      case  1: printf("|V1| > |V2|"); break;
      case -1: printf("|V1| < |V2|"); break;
      default: puts("Fehler!");
    }
    

    Du sparst wieder eine Variable (result).
    Als nächstes wäre eine Prüfung der Usereingaben bei scanf sinnvoll.


  • Mod

    Andromeda schrieb:

    Wutz schrieb:

    Andromeda schrieb:

    return (((amountv2-amountv1)<1)-1)|(amountv1!=amountv2);
    

    🙂

    Nonsens.
    Bitoperatoren auf negative int loszulassen ist einfach nur dumm und ahnlungslos.

    Dann check mal diese hübsche Variante: 😃

    return ((amountv2-amountv1)<0) - ((amountv2-amountv1)>0);
    

    Auch nicht besser. amount2v2-amountv1 oder amountv2-amountv1 kann immer noch überlaufen und UB bedingen.



  • camper schrieb:

    Auch nicht besser. amount2v2-amountv1 oder amountv2-amountv1 kann immer noch überlaufen und UB bedingen.

    Wie sollen die denn überlaufen?. Das sind beides nichtnegative Werte


  • Mod

    DirkB schrieb:

    camper schrieb:

    Auch nicht besser. amount2v2-amountv1 oder amountv2-amountv1 kann immer noch überlaufen und UB bedingen.

    Wie sollen die denn überlaufen?. Das sind beides nichtnegative Werte

    Ah stimmt, hätte mehr als die letzte Seite lesen sollen.
    Trotzdem witzig, dass über Mikrooptimierungen auf Assemblerebene diskutiert wird, anstatt erst mal auf das überflüssige Wurzelziehen zu verzichten.



  • camper schrieb:

    Trotzdem witzig, dass über Mikrooptimierungen auf Assemblerebene diskutiert wird, ...

    Gibt es da keine Signum-Funktion?

    camper schrieb:

    ... anstatt erst mal auf das überflüssige Wurzelziehen zu verzichten.

    Tja, erstmal die letzten Promille raus kitzeln, bevor wir dann die Prozente raus holen.



  • camper schrieb:

    Trotzdem witzig, dass über Mikrooptimierungen auf Assemblerebene diskutiert wird, anstatt erst mal auf das überflüssige Wurzelziehen zu verzichten.

    Jemand erwähnte, dass das if/elseif/else um den Rükgabewert zu kriegen, kürzer zu coden sei. Damit ging das los. 😃

    Aber du bringst mich auf eine Idee: anstatt die echte Länge des Vektors auszurechnen, müsste für einen Größenvergleich die Summe der Beträge der Komponenten ausreichend sein.

    Also statt: echte_laenge = sqrt (a*a + b*b + c*c + ...)
    richtwert = abs(a) + abs(b) + abs(c) + ...

    Oder?



  • Andromeda schrieb:

    Also statt: echte_laenge = sqrt (a*a + b*b + c*c + ...)
    richtwert = abs(a) + abs(b) + abs(c) + ...

    Nein, so einfach ist es dann doch nicht

    Die Quadrate musst du noch bilden, aber auf die Wurzel kannst du verzichten.
    Denn es gilt:
    0 ≤ d < f <=> 0 ≤ sqrt(d) < sqrt(f)



  • Andromeda schrieb:

    Jemand erwähnte, dass das if/elseif/else um den Rükgabewert zu kriegen, kürzer zu coden sei. Damit ging das los.

    Nein, mir geht es primär um zwei Dinge:
    - Lesbarkeit
    - Kürze

    Dann kommt Geschwindigkeit. Wenn du genug Erfahrung hast, kannst du alle drei kombinieren.

    Dein Code ist weniger gut lesbar, er mag kürzer im Quellcode sein, generiert aber mehr Maschinencode. Geschwindigkeit habe ich nicht getestet.

    Andromeda schrieb:

    Also statt: echte_laenge = sqrt (a*a + b*b + c*c + ...)
    richtwert = abs(a) + abs(b) + abs(c) + ...

    Oder?

    Ist nicht äquivalent. Das abs sparen wir uns mal grad:

    richtwert_falsch_1 = 10 + 5 + 5; /*20*/
    richtwert_falsch_2 = 20 + 0 + 0; /*20, würde also passen*/
    
    richtwert_korrekt_1 = 10*10 + 5*5 + 5*5; /*150*/
    richtwert_korrekt_2 = 20*20 + 0*0 + 0*0; /*400 - und plötzlich passt es nicht mehr*/
    

    Glücklicherweise sind Multiplikationen meines Wissens nicht so teuer wie Divisionen.



  • Dirk, Dachschaden: Danke! 🙂



  • Kurze Anekdote:

    Ein Programm lief sehr langsam, wenn man viele Variablen verwendete. perf hat mir als Verursacher die Funktion exp() angezeigt (über 40% der Gesamtlaufzeit).

    Es wurde vielfach für einen double-vector der Länge n für alle i,j aus [0..n-1], i!=j jeweils exp(v[i] - v[j]) berechnet. Berechnet man allerdings exp(i) für alle Elemente vor und macht dann eine Division statt der Subtraktion, wird der Code plötzlich wieder schnell... (in meinem Fall war n ~ 20)

    Also: gerade diese komplizierten Funktionen wie exp, sqrt, ln klug zu ersetzen oder gar ganz drauf zu verzichten, kann sich lohnen!



  • Wo wir grad so schön beim Thema sind ...

    float Q_rsqrt( float number )
    {
    	long i;
    	float x2, y;
    	const float threehalfs = 1.5F;
    
    	x2 = number * 0.5F;
    	y  = number;
    	i  = * ( long * ) &y;                       // evil floating point bit level hacking
    	i  = 0x5f3759df - ( i >> 1 );               // what the fuck? 
    	y  = * ( float * ) &i;
    	y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
    //	y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed
    
    	return y;
    }
    

    https://en.wikipedia.org/wiki/Fast_inverse_square_root


Anmelden zum Antworten