Berechnung am Rande des Wertebereichs



  • Hallo zusammen,

    ich möchte folgende Berechnung durchführen:

    long int nsec = 3.5e10 * / Baudrate; //Baudrate = 9600
    

    Eigentlich sollte dabei 3645833,333.. rauskommen (bzw. als Integer 3645833),

    tatsächlich sehe ich aber 66693, wenn ich nsec mit

    printf ("nsec = %u\n", nsec);
    

    ausgeben lasse.

    Wobei ich sagen muss, daß bei der printf-Anweisung eine Warnung kommt. (Weil mit %u offensichtlich kein long int dargestellt werden kann. Ich habe aber keine andere Möglichkeit gefunden.)
    Ich arbeite mit gcc 3.3.5

    Vielen Dank für Unterstützung,

    Gruß



  • Zuerst: Ganzzahl-Arithmetik arbeitet immer modulo MAXINT 😉
    Und zum zweiten: für long int heißt der Formatcode "%ld" bzw. "%lu".

    Edit: Und zum dritten: Der Ausdruck "nsec = 3.5e10 * / Baudrate" sieht mir stark nach einem Tippfehler aus 😉



  • Hallo,

    danke für die schnelle Antwort.

    1. Was heisst "arbeitet immer modula MAXINT"?
    2. OK, Danke!
    3. Du hast recht, sollte so heißen:

    nsec = 3.5e10 / Baudrate;
    

    Aber das eigentlich Problem besteht weiterhin.

    Gruß



  • Lazlo schrieb:

    1. Was heisst "arbeitet immer modula MAXINT"?

    Kurz gesagt: Wenn deine Ganzzahl den zulässigen Wertebereich von int (bzw. long) überschreitet, werden die oberen Bitstellen abgeschnitten.

    Kannst du mal zur Kontrolle ausgeben, was in Baudrate drin steht? Möglicherweise rechnest du dort mit einem falschen Wert.



  • Hallo,

    In Baudrate steht 9600 drin.

    Gruß



  • Was ist "Baudrate"? Eine Konstante (#define oder const)? Eine Variable? Lokal bezüglich deiner Funktion? Global? (etwa gar ein Char-Array mit dem Inhalt "9600"?)
    In deinem Code-Schnipselchen kann ich nämlich keine (logischen) Fehler erkennen, also könnte das Problem auch irgendwo drumherum liegen.

    Btw, es ist immer besser, eine Debug-Ausgabe zu setzen, als sich blind auf irgendwelche Werte zu verlassen 😉



  • Bei Baudrate handelt es sich um eine lokale Integer-Variable in der main()-Routine.

    initialisiert und deklariert mit:

    int baudrate = 9600;
    


  • *fasst das mal zusammen*

    int baudrate = 9600;
    
    //...
    
    long int nsec = 3.5e10 * / Baudrate;
    

    Dir ist klar, daß es hier um zwei verschiedene Variablen geht? (C ist sehr empfindlich mit der Groß/Kleinschreibung)



  • Hallo,

    Ja, das weiß ich. Da ich aber auf Linux programmiere und nur unter einem Windows-PC ins Netz gelange, treten diese Tippfehler auf... 😞
    (Baudrate wird also auch hier mit einem großen 'B' geschrieben.)

    Ich habe jetzt aber eine Lösung gefunden:

    double foo = (double) 3.5e10 / Baudrate;
    long int nsec = (long int) foo;
    

    Nicht sehr schön. Meine Vermutung, daß demnach

    long int nsec = (long int) (double) 3.5e10 / Baudrate;
    

    auch gehen müsste, hat sich jedoch nicht bestätigt. Mein Problem wäre eigentlich gelöst. Aus Interesse wüsste ich aber schon gerne, warum das so funktioniert und nicht anders. Oder gibt es noch eine Möglichkeit?



  • Lazlo schrieb:

    Nicht sehr schön. Meine Vermutung, daß demnach

    long int nsec = (long int) (double) 3.5e10 / Baudrate;
    

    auch gehen müsste, hat sich jedoch nicht bestätigt.

    versuch's mal mit der richtigen Klammerung:

    long int nsec = (long int) ((double)3.5e10 / Baudrate);
    

    (andernfalls konvertiert der Compiler 3.5e10 nach long und dividiert ganzzahlig - und der Wert ist ein Stück zu groß für long.


Anmelden zum Antworten