ich möchte die Funktionswerte der quadratischen Funktion
f(i)=(0.0000038 * i^2 - 0.0076 * i + 4) * 1000
als ganzzahlige (es kommt nicht auf die exakte Rundung an, somit ist die Umwandlung von double in int durch "Abschneiden" zulässig) Werte berechnen lassen. Ich habe jetzt schon einiges ausprobiert und gelesen (Überlauf ist bei Werten dieser Größe auszuschließen, soweit ich das beurteilen kann), jedoch ergibt sich in einem bestimmten Zahlenbereich immer ein Rechenfehler. Dieser ist reproduzierbar und taucht immer an der gleichen Stelle auf:
void setup() {
Serial.begin(9600);
for (int i = 1; i <= 1001; i++) {
double f = (0.0000038 * pow(i, 2) - 0.0076 * i + 4) * 1000;
int t = (int)f;
Serial.println(t);
}
}
void loop() {
}
Fügt man nach jeder Iteration ein delay() von einigen Millisekunden ein, ändert sich die Position des Fehlers bis man bei delay(100) keinen Fehler mehr hat. Allerdings dauert die Berechnung dann eindeutig zu lange. Ich habe schon an einen vorher berechneten Array gedacht, der die Funktionwerte dann nur ausließt, allerdings ist mir das zu inflexibel, da ich langfristig eine Funktion mit variablen Koeffizienten brauche.
Ich habe den Code sowohl auf einem Arduino Mega 2560 als auch auf einem Arduino Nano laufen lassen, jeweils mit ähnlichem Fehlverhalten. Der Fehler ist bislang nur einmalig pro Schleife aufgetreten.
Kann mir jemand sagen woher der Fehler kommt und wie man diesen beheben kann?
Vielen Dank!
Erstaunlicherweise liefert der Algorithmus nach dem An- und Ausschalten des Arduino bei mir ebenfalls die richtigen Werte. Ich kann mir nicht erklären wie sowas zu Stande kommt, aber sofern es jetzt funktioniert ist ja alles bestens. Ich habe soeben herausgefunden, dass sich -zumindest bei mir- der Fehler doch reproduzieren lässt, wenn man void loop(){} mitausführt. Woran könnte das liegen?
void setup() {
Serial.begin(9600);
for (int i = 1; i <= 1001; i++) {
double f = (0.0000038 * pow(i, 2) - 0.0076 * i + 4) * 1000;
int t = (int)f;
Serial.println(t);
}
}
void loop(){
}
jurs:
Vermeide Bereichsüberläufe in Deinen Variablen!
Der gültige Bereich Deiner als int t" deklarierten Variablen reicht von -32768 im negativen Bereich bis zu 32767 im positiven Bereich.
Inwiefern kann das zu einem Problem führen? Die Funktionswerte sind ja im Intervall 4000 bis 200. Da bin ich ja weit entfernt von den integer-Wertebereichsgrenzen. Oder könnte die Potenzierung zum Problem werden? pow(i,2) liefert bereits für 182 einen Wert größer als 32767. Anderseits funktioniert es jetzt ohne einen größeren Datentyp wie z.B. long.
Ich habe den Fehler jetzt gefunden, denke ich. Aus irgendeinem Grund führen beide Arduinos bei mir nach etwas 0,8s einen "kleinen Neustart" aus. Bedeutet, dass die Built-In-Lampe einmal aufleuchtet und das Ausführen des Codes kurz unterbrochen wird. Ich habe keinen Schimmer wieso, aber mit einem delay(1000) am Anfang des setup lässt sich das Problem beheben.
void setup() {
Serial.begin(9600);
delay(1000);
for (int i = 0; i <= 1000; i++) {
double f = (0.0000038 * pow(i, 2) - 0.0076 * i + 4) * 1000;
int t = (int)f;
Serial.println(t);
}
}
void loop(){}
combie:
Was das bedeuten mag...?
Ich nicht wissen.
Das Entfernen der Klasse (?) loop() führt bei mir zwar zu einer Fehlermeldung des Compilers, das Arduino Mega kann das Programm trotzdem ausführen und kommt auch auf die richtigen Funktionswerte.
void setup() {
Serial.begin(9600);
for (int i = 0; i <= 1000; i++) {
double f = (0.0000038 * pow(i, 2) - 0.0076 * i + 4) * 1000;
int t = (int)f;
Serial.println(t);
}
}
losredoe132:
Das Entfernen der Klasse (?) loop() führt bei mir zwar zu einer Fehlermeldung des Compilers, das Arduino Mega kann das Programm trotzdem ausführen und kommt auch auf die richtigen Funktionswerte.
loop() ist eine Funktion.
Der Rest ist abergläubischer Quatsch.
Das bisherige Programm wird in so einem Fall ausgeführt, niemals das neue.
Das bisherige Programm wird in so einem Fall ausgeführt, niemals das neue.
Was meinst du mit bisherig und neu? Kannst du mir den abergläubischen Quatsch den plausibel erklären? Denn es macht zumindest bei mir tatsächlich einen Unterschied ob ich die Funktion (danke) loop mit in den Code schreibe oder nicht.
combie:
Das, was du da zeigst ist kein Rechenfehler!
Sondern das Resultat eines Reset.
Ja, das hab ich jetzt auch als Problem identifiziert. Da ich den Restknopf nicht drückte, resetet sich mein Arduino scheinbar selbst. Was könnte die Ursache sein?
losredoe132:
Ja, das hab ich jetzt auch als Problem identifiziert. Da ich den Restknopf nicht drückte, resetet sich mein Arduino scheinbar selbst. Was könnte die Ursache sein?
Arduino-Boards haben eine "Auto-Reset" Funktion beim Öffnen des seriellen Monitors.
Wenn praktisch im selben Moment, in dem der serielle Monitor geöffnet wird, ein Reset auftritt, dann ist das die Auto-Reset Funktion des Boards.
Hallo,
ich denke, dass eine leere Funktion mindestens ein Semikolon enthalten muss. Der Compiler macht dann daraus den Befehl "NÓP" = no Operation.
void loop(){;}
Gruß Manfred