Näherungsweise der Euler'schen Zahl berechnen

Hallo alle zusammen!
Wir müssen in der Schule die Eulersche Zahl näherungsweise mit der Formel:

1+1/1+1/(12)+1/(123)+1/(1234) usw.

berechnen.
Ich habe aber noch ein paar Programmierprobleme und verstehe nicht wie ich das genau machen soll.

Ich verwende nur den Serial Monitor, also keine zusätzlichen Geräte.

Der Arduino soll näherungsweise an die Zahl e gehen, und dabei die Abweichung berechnen.

Kann mir hier irgendjemand weiterhelfen?
Vielen Dank für eure Hilfe im Voraus.

LG
Matthias

Dann zeige uns doch Deinen Sketch, den Du bisher hast und beschreibe Deine Probleme anhand dieses Sketches.

Setze Deinen Code bitte in Codetags (</>-Button oben mitte im Forumseditor oder gehe in der IDE auf Bearbeiten - Für Forum kopieren und füge es hier ein).
Dann ist er auch auf mobilen Geräten besser lesbar.

Gruß Tommy

Hallo

eine Formel hat ja links und rechts vom = was stehen. Ansonsten kannst Du mal erst was lesen
https://de.wikipedia.org/wiki/Eulersche_Zahl

Dann zerlegst Du die Aufgabe in Teilbereiche und fügst die Ergebnisse zusammen.

Heinz

Hat mich mal interessiert, wie man das einstielt, ohne ein einzigen Byte RAM oder Flash zu beanspruchen.
Rekursiv und doch ohne Stack verbrauch.

So sieht das dann aus: (so kann das dann aussehen)

// Fakultät n=rechentiefe
template<uint64_t n>struct fac{constexpr operator uint64_t(){return fac<n-1>()*n;}};
template<>struct fac<0>{constexpr operator uint64_t(){return 1;}};

// Eulersche Zahl k=rechentiefe
template<unsigned k>struct euler{constexpr operator float(){return euler<k-1>()+1e0/fac<k>();}};
template<>struct euler<0>{constexpr operator float(){return 1e0;}};

// eine Tiefe von 9 ist für AVR float ausreichend
constexpr float eulerZahl = euler<9>();
//constexpr float eulerZahl = M_E;

Leider entspricht das dann nicht mehr der Anforderung im Eingangs Posting, dass es auf dem Arduino laufen soll, denn es wird vollständig im Kompiler abgehandelt.

Auf wieviele Nachkommastellen? 23? 16? ??

Hallo matthias36078
sketched du noch oder hast du schon eine Lösung :sunglasses:

Hallo!
Mein Ansatzcode sieht so aus:

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
float e=2,p=1,z=1,d=1;


Serial.println(" Durchlauf    exp()         Nenner        Abweichung ");

while(d>=-0|) {  // Bedingung bis e erreicht ist
 z=d;
  Serial.print(z,10); //10 .. Nachkommastellen beid er Ausgabe
  Serial.print("  ");
  Serial.print(e,10); //aktuelle Zahle e
  Serial.print("  ");
  Serial.print(p,10); //Nenner des Summanden
  Serial.print("  ");
  Serial.println(z,10);
  //Neue Berechnung

}
}

void loop() {
  // put your main code here, to run repeatedly:

}

Im Angang sieht man ein Bild, wie es zum Schluss aussehen soll.
Serial Monitor

Es soll jede Ausgabe auf 10 Nachkommastellen gerundet werden, das geht doch mit Serial.print(Variable,10).

Ich komme irgendwie mit der Formel nicht weiter.
Kann mir da wer einen Tipp geben?

LG
Matthias36078

Hallo

was heisst bis e erreicht ist ? vermutlich wirst Du das nie erreichen. Bedenke der Arduino UNO rechnet mit etwa 6 stellen Genauigkeit bei realen (float) Zahlen.
ich hatte ja schon mal einen Tipp gegeben. Erst mal eine richtige Formel suchen. Das was Du da geschrieben hast ist falsch.

ich würde das erst mal in drei Schritte aufteilen
Fakultät berechnen 1-n
Terme (Brüche) berechnen 1-n
Summe berechnen 1-n

dazu kannst Du ein zwei Array´s verwenden und dann für jeden Schritt eine Schleife aufbauen. Über alles kannst Du dann nochmals eine Schleife bauen um das n zu erhöhen. Wenn Du die Formel in eine Zeile schreiben willlst verlierst Du den Überblick.

Also für Dich als Grundlage
Zahlenbereicher der Variabelntypen festlegen
Was sind Arrays
was ist eine for.. schleife
Dann gehst Du nacheinander an die drei Schritte und verwendest immer schön ein paar Seriell.print() auf dem Monitor um das zu kontrollieren.
Heinz

Hallo!
Ich habe es jetz ungefähr mit diesem Code hinbekommen:

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
float e=2,p=1,z=1,d=1;


Serial.println(" Durchlauf    exp()         Nenner        Abweichung ");

while(d>=0) {

  Serial.print(z,10); //Zähler
  Serial.print("  ");
  Serial.print(e,10); //aktuelle Zahle e
  Serial.print("  ");
  Serial.print(p,10); //Nenner des Summanden
  Serial.print("  ");
  Serial.print(d,10);
  Serial.println("");

e=exp(1)/(e-p);
p=e*d;
d=exp(1)-e;
z++;
}
}

void loop() {
  // put your main code here, to run repeatedly:

}

Die Eulersche Zahl habe ich bis auf 6 Nachkommerstellen genau.
Danke für euer Bemühen!
LG
Matthias36078

Hallo,

wenn Du meinst dann wird das schon so sein :wink:

Heinz

Der zeigt mir:

 Durchlauf    exp()         Nenner        Abweichung 
1.0000000000  2.0000000000  1.0000000000  1.0000000000
2.0000000000  2.7182817459  2.7182817459  0.0000000000

Müsste es nicht eigentlich so aussehen?

k      teiler        euler        abweichung
0            1   1.0000000000   1.7182817459
1            1   2.0000000000   0.7182817459
2            2   2.5000000000   0.2182817459
3            6   2.6666667461   0.0516149997
4           24   2.7083334922   0.0099482536
5          120   2.7166669368   0.0016148090
6          720   2.7180557250   0.0002260208
7         5040   2.7182540893   0.0000276566
8        40320   2.7182788848   0.0000028610
9       362880   2.7182817459   0.0000000000

Hallo!
Ja eigentlich sollte es direkt so aussehen.
Hast du etwas an der Formel geändert?
LG
Matthias36078

Hallo
was soll eigentlich der Teiler aussagen, letztlich sind es doch Teiler mehrere Brüche.

en=1 + 1/1! + 1/2! + 1/3! + 1/n!

Matthias36078 irgendwie musst Du die Formel schon verwenden.

n 	 Näherung	 	 e 			       Differenz 
1	1.000000000000	2.718281828459	1.718281828459
2	2.000000000000	2.718281828459	0.718281828459
3	2.500000000000	2.718281828459	0.218281828459
4	2.666666666667	2.718281828459	0.051615161792
5	2.708333333333	2.718281828459	0.009948495126
6	2.716666666667	2.718281828459	0.001615161792
7	2.718055555556	2.718281828459	0.000226272903
8	2.718253968254	2.718281828459	0.000027860205
9	2.718278769841	2.718281828459	0.000003058618
10	2.718281525573	2.718281828459	0.000000302886
11	2.718281801146	2.718281828459	0.000000027313
12	2.718281826198	2.718281828459	0.000000002261
13	2.718281828286	2.718281828459	0.000000000173
14	2.718281828804	2.718281828459	-0.000000000345
15	2.718281829586	2.718281828459	-0.000000001127
16	2.718281830085	2.718281828459	-0.000000001626

Richtig genau ungenau wird es mit einem ESP8266 mit double. Ab n=16 wird der Feher dann wieder grösser zumindest in meiner Variante :wink:

Heinz

Nein!
Ich habe deine Abbruchbedingung verwendet, und die Summen-Formel aus Wikipedia.
Siehe hier die Reihe:

Hallo!
Diese Reihe habe ich ja oben auch gemeint. Nur weiß ich nicht wie ich die schreiben soll.
Hast du die Abbruchbedingung mit einer If - Satz gemacht?
Also wenn Abweichung 0 ist, soll er aufhören zu zählen?
LG
Matthias 36078

Hallo
Dann lies dir #9 nochmal durch
Heinz

Klar, kann ich dir zeigen, wie das bei mir aussieht:

Das wirkt als Abbrucherkennung:

  operator bool()
  {
    return M_E-euler >= 0;
  }

Und hier kommt sie (die Abbruchbedingung) dann zum Einsatz:

void setup() 
{
  Serial.begin(9600);
  Serial.println();
  Serial.println("k      teiler        euler        abweichung");
  
  for(Euler e;e;e++)Serial.println(e);
}

Und nein, was "Euler" ist und tut, halte ich erstmal geheim, denn es ist ja deine Aufgabe das zu lernen, zu verstehen, wie man das baut/rechnet. Da hilft es nix, wenn du bei mir abschreibst. Zudem ist meine Variante so "naja", dass du damit direkt durch die Prüfung rasselst.

Wenn du das Prinzip erstmal verstanden hast, dann gibts 1000 Varianten, wie man das ausformulieren kann, da brauchst du meine Variante nicht.

Aber wie schon gesagt: Mein Euler hält sich streng an die Summenformel.
Nur, dass es eben nicht mit k gegen unendlich läuft, sondern nach deinem Prinzip die Schleife abbricht.

Hallo!
Würdest du dir nicht die for Schleife ersparen, wenn du eine while Schleife verwendest?
Bei einer While Schleife wird doch der Code so lange durchgeführt, bis die Bedingung erfüllt ist, oder?
LG
Matthias36078

Hallo,
ich will dich mal was anstubsen, hier mal ein einfacher Ansatz ohne Array wie man die Fakultät berechnen kann. Damit kannst Du ja jetzt mal anfangen. Ergänzen und aufhübschen überlass ich Dir.
Heinz

uint32_t fk_n_minus1 = 1;
uint32_t fk_n;// Fakultät von n
byte i=1;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}
void loop() {
  // put your main code here, to run repeatedly:
  if (i <=10) {
    fk_n = fk_n_minus1 * i;
    Serial.print(i); Serial.print("\t");
    Serial.println(fk_n);
    i++;
    fk_n_minus1 = fk_n;// neuen Wert im alten ablegen
  }

}

ja schon , aber was ist die Abbruchbedingung ? Eventuell wird das = ja nie erreicht. Da macht es doch mehr Sinn bei einem festen n aufzuhören. Natürlich kannst Du auch eine kleine Differenz als Abbruch nehmen, eine die Deinen Anforderungen genügt. Schau dir mal #14 an , was würdest Du da nehmen ohne das Du das Ergebniß vorher kennst. Eventuell gerätst Du in eine Endlosschleife aus der Du nicht mehr rauskommst und dann ist Dein System blokiert.

Heinz