Vektoren vergleich in C



  • Das heißt, wenn ich X1,X2,X3,Y1,Y2,Y3 gar nicht mehr benötige, darf der Code dann so aussehen?

    #include <stdio.h>
    #include <math.h>
    
    int compVecLen(int v1[], int v2[]); char result;
    int X1,X2,X3,Y1,Y2,Y3;
    int A1,A2,A3,B1,B2,B3;
    int c,d;
    int amountv1, amountv2;
    int main()
    
    {
    
    int V1[3]={X1,X2,X3};
    int V2[3]={Y1,Y2,Y3};
    
    printf("Enter the values of Vector 1");
    scanf("%d",&V1[0]);
    scanf("%d",&V1[1]);
    scanf("%d",&V1[2]);
    
    printf("Enter the values of Vector 2");
    scanf("%d",&V2[0]);
    scanf("%d",&V2[1]);
    scanf("%d",&V2[2]);
    
    result=compVecLen(V1,V2);
    
    if(result=d)
    {
    printf("|V1| > |V2|");
    }
    if(result=c)
    {
    printf("|V1| < |V2|");
    }
    else
    {
    printf("|V1| = |V2|");
    }
    
    return 0;
    
    }
    
    int compVecLen(int v1[3], int v2[3])
    
    {
    
    amountv1=sqrt(v1[1]*v1[1]+v1[2]*v1[2]+v1[3]*v1[3]);
    amountv2=sqrt(v2[1]*v2[1]+v2[2]*v2[2]+v2[3]*v2[3]);
    
    if(amountv1<amountv2)
    {
    return c;
    }
    
    if(amountv1>amountv2)
    {
    return d;
    }
    
    else
    {
    return 0;
    }
    
    }
    

    Und die eingegebenen Daten in das Array zu initialisieren sähe dann so aus?

    #include <stdio.h>
    #include <math.h>
    
    int compVecLen(int v1[], int v2[]); char result;
    int X1,X2,X3,Y1,Y2,Y3;
    int A1,A2,A3,B1,B2,B3;
    int c,d;
    int amountv1, amountv2;
    int main()
    
    {
    
    int V1[3]={X1,X2,X3};
    int V2[3]={Y1,Y2,Y3};
    
    printf("Enter the values of Vector 1");
    scanf("%d",&X1);
    scanf("%d",&X2);
    scanf("%d",&X3);
    
    printf("Enter the values of Vector 2");
    scanf("%d",&Y1);
    scanf("%d",&Y2);
    scanf("%d",&Y3);
    
    X1=V1[0];
    X2=V1[1];
    X3=V1[2];
    Y1=V2[0];
    Y2=V2[1];
    Y3=V2[2];
    
    result=compVecLen(V1,V2);
    
    if(result=d)
    {
    printf("|V1| > |V2|");
    }
    if(result=c)
    {
    printf("|V1| < |V2|");
    }
    else
    {
    printf("|V1| = |V2|");
    }
    
    return 0;
    
    }
    
    int compVecLen(int v1[3], int v2[3])
    
    {
    
    amountv1=sqrt(X1*X1+X2*X2+X3*X3);
    amountv2=sqrt(Y1*Y1+Y2*Y2+Y3*Y3);
    
    if(amountv1<amountv2)
    {
    return c;
    }
    
    if(amountv1>amountv2)
    {
    return d;
    }
    
    else
    {
    return 0;
    }
    
    }
    

    Erhalte allerdings weiterhin das Else Statement als Ausgabe...



  • gcc.godbolt.org mit clang 3.8 und -Wall als Parameter liefert dir noch ein bisschen was zum schauen



  • Gast3 schrieb:

    gcc.godbolt.org mit clang 3.8 und -Wall als Parameter liefert dir noch ein bisschen was zum schauen

    Leider verstehe ich dabei nur böhmische Dörfer 😕
    ich versuche zwar in etwa nachzuvollziehen, was dort passiert, aber mit der Ansicht ziemlich überfordert. Hast du noch einen Tipp?



  • Bin leider völlig mit meinem Latein am Ende. Vorher wusste ich zwar auch nicht genau, WAS falsch war, aber ich hatte das Gefühl, dass etwas nicht stimmen konnte. Jetzt, egal wie oft ich den Code Zeile für Zeile durchgehe, denke ich, dass es doch eigentlich stimmen müsste..

    Edit: Folgendes: müsste es bei den if-Statements mit Result nicht '==' heißen? Wenn ich das tue, erfolgt bei jeglicher Werteingabe das Statement von result==d UND result==c.



  • Tergo schrieb:

    Leider verstehe ich dabei nur böhmische Dörfer 😕
    ich versuche zwar in etwa nachzuvollziehen, was dort passiert, aber mit der Ansicht ziemlich überfordert. Hast du noch einen Tipp?

    Du bist davon überfordert, die Warnung, die dein Code produziert, nachzuvollziehen? Das ist in weniger als 5 Sekunden zu finden und in zwei Sekunden zu fixen.

    Tergo schrieb:

    Edit: Folgendes: müsste es bei den if-Statements mit Result nicht '==' heißen? Wenn ich das tue, erfolgt bei jeglicher Werteingabe das Statement von result==d UND result==c.

    Bingo. Jetzt schau dir noch mal genau ab, wie dein if-else Konstrukt aussieht, da fehlt nämlich auch was.

    Wann werden c und d gesetzt?



  • dachschaden schrieb:

    Tergo schrieb:

    Leider verstehe ich dabei nur böhmische Dörfer 😕
    ich versuche zwar in etwa nachzuvollziehen, was dort passiert, aber mit der Ansicht ziemlich überfordert. Hast du noch einen Tipp?

    Du bist davon überfordert, die Warnung, die dein Code produziert, nachzuvollziehen? Das ist in weniger als 5 Sekunden zu finden und in zwei Sekunden zu fixen.

    Ich dachte eher, dass Hauptaugenmerk liegt auf der linken Seite. Die einzige Warnung, die dann kam, drehte sich um das result==c und result==d, welches ich nun behoben habe. Die Berechnung wird jedoch weiterhin nicht richtig ausgeführt. Gcc Godbolt spuckt keine weiteren Warnungen aus.

    Dementsprechend sieht der Code nun wie folgt aus:

    #include <stdio.h>
    #include <math.h>
    
    int compVecLen(int v1[], int v2[]); char result;
    int X1,X2,X3,Y1,Y2,Y3;
    int A1,A2,A3,B1,B2,B3;
    int c,d;
    int amountv1, amountv2;
    int main()
    
    {
    
    int V1[3]={X1,X2,X3};
    int V2[3]={Y1,Y2,Y3};
    
    printf("Enter the values of Vector 1");
    scanf("%d",&X1);
    scanf("%d",&X2);
    scanf("%d",&X3);
    
    printf("Enter the values of Vector 2");
    scanf("%d",&Y1);
    scanf("%d",&Y2);
    scanf("%d",&Y3);
    
    X1=V1[0];
    X2=V1[1];
    X3=V1[2];
    Y1=V2[0];
    Y2=V2[1];
    Y3=V2[2];
    
    result=compVecLen(V1,V2);
    
    if(result==d)
    {
    printf("|V1| > |V2|");
    }
    if(result==c)
    {
    printf("|V1| < |V2|");
    }
    else
    {
    printf("|V1| = |V2|");
    }
    
    return 0;
    
    }
    
    int compVecLen(int v1[3], int v2[3])
    
    {
    
    amountv1=sqrt(X1*X1+X2*X2+X3*X3);
    amountv2=sqrt(Y1*Y1+Y2*Y2+Y3*Y3);
    
    if(amountv1<amountv2)
    {
    return c;
    }
    
    if(amountv1>amountv2)
    {
    return d;
    }
    
    else
    {
    return 0;
    }
    
    }
    


  • 'c' und 'd' werden eingesetzt, wenn amountv1<amountv2 bzw. amountv1>amountv2 ergibt



  • Tergo schrieb:

    Ich dachte eher, dass Hauptaugenmerk liegt auf der linken Seite.

    Weil da auch der Compiler-Output rauskommt, wa? Oh, nee, warte, das war der Input ... 🙄

    Tergo schrieb:

    Die einzige Warnung, die dann kam, drehte sich um das result==c und result==d, welches ich nun behoben habe. Die Berechnung wird jedoch weiterhin nicht richtig ausgeführt. Gcc Godbolt spuckt keine weiteren Warnungen aus.

    Joa, das heißt halt, dass dein Programm syntaktisch korrekt ist, aber semantisch halt nicht. Sprich, du hast noch Fehler drinne, die dafür sorgen, dass es nicht so läuft, wie beabsichtigt.

    Der Compiler kann dich vor einigen Fehlern warnen, aber bei weitem nicht vor allen.

    Tergo schrieb:

    'c' und 'd' werden eingesetzt, wenn amountv1<amountv2 bzw. amountv1>amountv2 ergibt

    Die Frage war "Wann werden diese gesetzt?", nicht "eingesetzt".
    Du verwendest diese Variablen, ohne ihnen einen Wert zugewiesen zu haben. Globale und statische Variablen werden immer mit 0 initialisiert, d.h. dass du in jedem Fall immer und immer 0 zurückgibst in compVecLen .

    Ich würde deinem Dozenten mal auf den Tisch kotzen, wenn ich du wäre, offensichtlich weißt du nicht, was du tust.



  • Entschuldigung, hatte mich verschrieben, ich meinte die rechte Seite..

    Kann ich den Fehler beheben indem ich die if Statements der Funktion wie folgt ändere?:

    if(amountv1<amountv2)
    {
    return result=c;
    }
    
    if(amountv1>amountv2)
    {
    return result=d;
    }
    
    else
    {
    return 0;
    }
    


  • Tergo schrieb:

    Kann ich den Fehler beheben indem ich die if Statements der Funktion wie folgt ändere?

    Du liest meinen Text nicht durch. Du weißt c und d einfach nie zu. Und dein if-else -Konstrukt ist immer noch kaputt, das sollte

    if(x)
        {bla1}
    else if(y)
        {bla2}
    else
        {bla3}
    

    sein.



  • Der Code ist jetzt fertig und deutlich entschlackt. Das Programm gibt richtige Ergebnisse raus, habe ich noch irgendwas vergessen? Vielen lieben Dank für die Hilfe bereits im Voraus!

    #include <stdio.h>
    #include <math.h>
    
    int compVecLen(int v1[], int v2[]); 
    int result;
    int main()
    
    {
    
    int V1[3];
    int V2[3];
    
    printf("Enter the values of Vector 1");
    scanf("%d",&V1[0]);
    scanf("%d",&V1[1]);
    scanf("%d",&V1[2]);
    
    printf("Enter the values of Vector 2");
    scanf("%d",&V2[0]);
    scanf("%d",&V2[1]);
    scanf("%d",&V2[2]);
    
    result=compVecLen(V1,V2);
    
    if(result == 0)
    {
    printf("|V1| = |V2|");
    }
    else if(result == 1)
    {
    printf("|V1| > |V2|");
    }
    else
    {
    printf("|V1| < |V2|");
    }
    
    return 0;
    
    }
    
    int compVecLen(int v1[], int v2[])
    
    {
    
    int amountv1=sqrt(v1[0]*v1[0] + v1[1]*v1[1] + v1[2]*v1[2]);
    int amountv2=sqrt(v2[0]*v2[0] + v2[1]*v2[1] + v2[2]*v2[2]);
    
    if(amountv1<amountv2)
    {
    return -1;
    }
    
    if(amountv1>amountv2)
    {
    return 1;
    }
    
    if(amountv1==amountv2)
    {
    return 0;
    }
    
    }
    


    • int main() macht man so in C++. In C sollte es int main(void) sein. Jede Funktion, die keinen Parameter übernimmt, sollte void in der Parameterliste haben.
    • result ist immer noch global, sollte lokal in main definiert werden.
      - fehlende Einrückung.
    • compVecLen geht kürzer:
    int compVecLen(int v1[], int v2[])
    {       
            int amountv1 = sqrt(v1[0]*v1[0] + v1[1]*v1[1] + v1[2]*v1[2]);
            int amountv2 = sqrt(v2[0]*v2[0] + v2[1]*v2[1] + v2[2]*v2[2]);
    
            if(amountv1 < amountv2)
                    return -1;
            if(amountv1 > amountv2)
                    return 1;
            return 0;
    }
    
    • sqrt gibt einen double zurück, keinen int . Das könnte dazu führen, dass Vektoren, die nicht gleichwertig sind, dennoch gleichwertig angesehen werden.


  • Habe int main() gelassen, weil wir es während der Vorlesung und im Praktikum immer so stehen haben lassen, zumindest bisher. Die Einrückungen kommen dann auf das finale Papier!

    #include <stdio.h>
    #include <math.h>
    
    int compVecLen(int v1[], int v2[]); 
    int main()
    
    {
    
    int result; 
    int V1[3];
    int V2[3];
    
    printf("Enter the values of Vector 1");
    scanf("%d",&V1[0]);
    scanf("%d",&V1[1]);
    scanf("%d",&V1[2]);
    
    printf("Enter the values of Vector 2");
    scanf("%d",&V2[0]);
    scanf("%d",&V2[1]);
    scanf("%d",&V2[2]);
    
    result=compVecLen(V1,V2);
    
    if(result == 0)
    {
    printf("|V1| = |V2|");
    }
    else if(result == 1)
    {
    printf("|V1| > |V2|");
    }
    else
    {
    printf("|V1| < |V2|");
    }
    
    return 0;
    
    }
    
    int compVecLen(int v1[], int v2[])
    
    {
    
    double amountv1=sqrt(v1[0]*v1[0] + v1[1]*v1[1] + v1[2]*v1[2]);
    double amountv2=sqrt(v2[0]*v2[0] + v2[1]*v2[1] + v2[2]*v2[2]);
    
    if(amountv1<amountv2)
    {
    return -1;
    }
    
    if(amountv1>amountv2)
    {
    return 1;
    }
    
    return 0;
    
    }
    


  • Noch ein Hinweis, warum dein 2. korrigierter Code mit der Zuweisung nicht so funktioniert hat -> du mußt die Zuweisung umdrehen (denn du möchtest ja das Array mit den Werten X1, X2 etc. initialisieren):

    V1[0] = X1;
    V1[1] = X2;
    // ...
    

    Abschließend noch die Variante mit der direkten Initialisierung nach der Eingabe:

    printf("Enter the values of Vector 1");
    scanf("%d",&X1);
    scanf("%d",&X2);
    scanf("%d",&X3);
    
    printf("Enter the values of Vector 2");
    scanf("%d",&Y1);
    scanf("%d",&Y2);
    scanf("%d",&Y3);
    
    /* Blockklammern für C89/C90 - nicht nötig bei C99 */
    {
        int V1[3]={X1,X2,X3};
        int V2[3]={Y1,Y2,Y3};
    
        result = compVecLen(V1,V2);
    
        // ...
    }
    


  • Vielen lieben Dank 🙂

    Wenn es dann da so steht, scheint alles so verdammt logisch.. Bei der nächsten Aufgabe werde ich auf solche Fehler besonders Acht geben!



  • Tergo schrieb:

    Die Einrückungen kommen dann auf das finale Papier!

    Darf man fragen warum? Einrückungen sollen dem Programmierer das Lesen des Codes leichter machen und nicht nur weil es andere Leute so wollen.



  • dachschaden schrieb:

    • compVecLen geht kürzer:
    int compVecLen(int v1[], int v2[])
    {       
            int amountv1 = sqrt(v1[0]*v1[0] + v1[1]*v1[1] + v1[2]*v1[2]);
            int amountv2 = sqrt(v2[0]*v2[0] + v2[1]*v2[1] + v2[2]*v2[2]);
      
            if(amountv1 < amountv2)
                    return -1;
            if(amountv1 > amountv2)
                    return 1;
            return 0;
    }
    

    Geht sogar noch kürzer mit dem Ternary OP, oder sogar Branch free. 🙂



  • Andromeda schrieb:

    Geht sogar noch kürzer mit dem Ternary OP, oder sogar Branch free. 🙂

    Sobald du auch nur einmal den Optimizer drüberlaufen lässt, produziert der Compiler exakt den gleichen Maschinencode (wir reden nicht mal von hohen Stufen; -O1 genügt). Kürzer, vielleicht. Lesbarer?

    #if 0
            if(amountv1 < amountv2)
                    return -1;
            if(amountv1 > amountv2)
                    return 1;
            return 0;
    #else
            return (amountv1 < amountv2 ? -1 : (amountv1 > amountv2 ? 1 : 0));
    #endif
    

    Finde die erste Variante deutlich lesbarer. Also bleib bei der ersten Variante, es sei denn, der Optimizer fällt einem wirklich auf den Fuss.



  • dachschaden schrieb:

    Andromeda schrieb:

    Geht sogar noch kürzer mit dem Ternary OP, oder sogar Branch free. 🙂

    Sobald du auch nur einmal den Optimizer drüberlaufen lässt, produziert der Compiler exakt den gleichen Maschinencode (wir reden nicht mal von hohen Stufen; -O1 genügt). Kürzer, vielleicht. Lesbarer?

    #if 0
            if(amountv1 < amountv2)
                    return -1;
            if(amountv1 > amountv2)
                    return 1;
            return 0;
    #else
            return (amountv1 < amountv2 ? -1 : (amountv1 > amountv2 ? 1 : 0));
    #endif
    

    Finde die erste Variante deutlich lesbarer. Also bleib bei der ersten Variante, es sei denn, der Optimizer fällt einem wirklich auf den Fuss.

    Probier mal das:

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

    🙂



  • Andromeda schrieb:

    Probier mal das:

    Schlechter lesbar, produziert noch mehr Maschinencode, und die Jumps sind immer noch nicht weg:

    movapd xmm0,xmm1
    mov    QWORD PTR [rsp+0x8],rsi
    call   400650 <sqrt@plt>
    mov    rsi,QWORD PTR [rsp+0x8]
    jmp    40088c <compVecLen+0x2c>
    movapd xmm0,xmm1
    call   400650 <sqrt@plt>
    jmp    4008b7 <compVecLen+0x57>
    

    Diesen Block hast du in beiden Varianten, nur dein Code macht noch mehr Zeug, was den Code nur aufbläht.


Anmelden zum Antworten