Wie eine Mulitplikation rechnen?

L I V E Stammtisch ab 20:30 Uhr im Chat
  • Ich möchte einen ATTiny13 flashen.

    Hierzu möchte ich eine Timer-Off-Zeit in Minuten eingeben. Die Minutenzahl wird dann mit 60 Sekunden und entsprechend 1000 ms multipliziert. Leider funktioniert das aber nicht.

    Code
    .
    .
    unsigned long TimerOffZeitinMin   = ((1*60*1000)-ZeitbisAutoOff);
    .
    .

    Wenn hingegen

    Code
    .
    .
    unsigned long TimerOffZeitinMin   = ((60000)-ZeitbisAutoOff);
    .
    .

    eingegeben wird, dann funktioniert es.

    Kann der kleine Tiny nicht multiplizieren oder muss ich einen anderen Variablen-Typ nehmen?

  • Ich mache das immer mit der Arduino IDE und einer Erweiterung für den entsprechenden µC.

    In diesem Fall wäre das die Erweiterung:

    https://mcudude.github.io/MightyCore/pac…Core_index.json

    Die ist natürlich eingestellt. Es funktioniert ja auch soweit alles so wie es soll, nur eben leider nicht die Multiplikation.

  • Was passiert, wenn du das äußere (überflüssige) Klammerpaar weglässt?

    Multiplikation ist bei CPUs eine der essentiellen Operationen, das muss am Code liegen...

    Vielleicht ... hm. hast du mal die Ausgabe aller Fehler und Warnings beim Übersetzten in der Arduino-IDE eingeschaltet und siehst etwas auffälliges?

  • Mal ne Frage am Rande: Du sagst, es funktioniert nicht... Was passiert denn? Kommen falsche Werte oder bringt er nen Fehler beim Kompilieren?

    Oh, man kann hier unliebsame Nutzer blockieren. Wie praktisch!

  • Die äußeren Klammern weg zu lassen bringt keine Besserung.

    Ziel dieser Zeile ist, dass nach einer vorgegebenen Zeit eine If-Anweisung ausgeführt wird.

    Der Fehler ist, dass dies nicht statt findet, wenn es als Multiplikation dort steht. Nehme ich aber das Ergebnis als Zahl, dann funktioniert es.

    Fehler beim Kompilieren tauchen nicht auf.

  • Es gibt immer mal kleine Macken, gerade wenn man so ein vergessenes Teil wie den 13ner nutzt. Da hat sich jemand ganz aktuell um einen Core für den 13er gekümmert. Vielleicht ist es wirklich "nur" ein Fehler in der Unterstützung vom "MightyCore" und der MicroCore läuft besser. Kannst ja mal probieren.

    https://github.com/mcudude/MicroCore

  • Das liegt daran, dass die kleinen Zahlen (vermutlich) erstmal als unsigned integer (-32768 bis 32767) behandelt werden. Deshalb erhältst Du einen Überlauf...

    Hier ist ein sehr ähnliches Problem: unsigned long rechnen mit großen Zahlen.

    Analog dazu müsste Dein Befehl wie folgt lauten:

    C
    unsigned long TimerOffZeitinMin   = ((1UL*60*1000)-ZeitbisAutoOff);

    ...wenn Software nicht so hard-ware ;) ...

    Freue mich über jeden like :thumbup:

  • Wird die If-Anweisung nie ausgeführt oder nur verfrüht oder verspätet (möglicherweise erst nach der hundertmillionenfachen Zeit)?

    60.000 ist ein unsigned int oder ein long Datentyp.

    1 * 60 * 1000 wäre Byte * Byte * int oder so ähnlich - Ich nehme mal an, er rechnet dann erst mal mit int und dann kommt ein Überlauf.

    Wenn du in der Formel 1000UL angibst, müsste er doch die 1000 als unsigned long annehmen und auch die gesamte Rechnung so machen.

    Es nützt glaube ich nichts, erst das Ergebnis als unsigned long zu definieren, wenn vorher die Rechnung mit kleineren Datentypen erfolgt.

    Ich versteh nicht viel von dem Thema Typumwandlung, aber ich hab mal was gelesen, das erschien mir recht komplex im Hintergrund. Sicher wäre es sinnvoll, zu sehen, was der Compiler da gemacht hat, als rumzuorakeln. Hast du dir mal das Ergebnis der Berechnung anzeigen lassen? Kannst du mal mit dem Serialmonitor prüfen, was in beiden Fällen bei der Rechnung rauskommt oder dir die Datentypen seriell anzeigen lassen?

    Oh, man kann hier unliebsame Nutzer blockieren. Wie praktisch!

  • Ah, zu spät - VeryPrivat hat die UL-Variante schon ins Spiel gebracht. Dann wars wohl das, was ich vermutet habe. Er hat intern mit einem kleineren Datentyp gearbeitet und wegen Überlauf dann wohl ne negative Zahl rausbekommen, die dein Script nie erreicht hat.

    Oh, man kann hier unliebsame Nutzer blockieren. Wie praktisch!

  • Das liegt daran, das in C vor einer arithmetischen Operation die Operanden geprüft werden.

    Da gibt es eine Hierachie:

    qfloat

    long double

    double

    float

    long long

    long

    short int

    char

    Vor der Operation werden die Operanden in den Typ konvertiert, welcher in der Hierachie am höchsten steht.

    Beispiel:

    int w;

    int x;

    float y;

    double z;

    z = x * y; x wird nach float konvertiert, das Produkt nach double.

    y = w * x; Die Multiplikation wird mit zwei Integern durchgeführt, und das Produkt nach float konvertiert.

    Die Multiplikation ist schnell, aber Vorsicht vor Überläufen. Die werden nicht abgefangen.

    Beit 4-Byte Integern wird 80000 * 80000 dann zu 2105032704.

    Die Zahlen innerhalb Deiner Klammen werden als "signed int" deklariert, weil nicht anders vorgegeben.

    Durch die Klammern, hast Du den Compiler explizit angewiesen die Multiplikationen innerhalb der Klammen mit

    dem Typ "signed int" durchzuführen zu lassen.

    Bei Deinem System scheint sizeof (int) gleich 2 zu sein.

    Einmal editiert, zuletzt von Prittzl (23. Februar 2019 um 15:02)

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!