2017-09-03 2 views
0

Ich versuche, die Genauigkeit und Fehler für die Maschine Epsilon zu finden. Ohne std :: numeric_limits zu verwenden. Ich erhielt die folgende Formel von meinem Professor y = 1-x/2^n, n> 1. Ich nehme an, dass y die Maschine Epsilon ist, x ist 1,0, und n sollte die Präzision sein.Maschine Epsilon Berechnung Fehler in C++

Hier ist meine Header-Datei macEpsFloat.hpp:

class MacEpsFloat 
{ 

public: 

    int precision(int n); 

private: 
    float e = 1.0; //error 
    float x = 1.0; //variable 
    float y = 0.0; //variable 
    int prec = 0; 
}; 

Hier ist meine macEpsFloat.cpp

Datei
int MacEpsFloat::precision(int n) 
{ 
    y = 1 - (x/(1<<n)); 

    if (y == 1.0) 
    { 
     prec = n-1; 
    } 
    else 
    { 
     float error = std::abs(e - y); 
     std::cout << "Error: " << error << std::endl; 
     ++n; 
     precision(n); 
    } 
    return prec; 
} 

Hier main.cpp ist

#include <iostream> 
#include "macEpsFloat.hpp" 


int main() 
{ 

    MacEpsFloat a; 

    std::cout << "Precision Float: " << a.precision(1) << std::endl; 
    std::cout << std::endl; 

} 

Die Variable y wird gleich 1,0 gesetzt, e wird gleich 1,0 gesetzt, und n wird gleich 1 gesetzt.

bekomme ich folgende Ausgabe:

error: 0.5 
error: 0.25 
error: 0.125 
error: 0.0625 
error: 0.03125 
error: 0.015625 
error: 0.0078125 
error: 0.00390625 
error: 0.00195312 
error: 0.000976562 
error: 0.000488281 
error: 0.000244141 
error: 0.00012207 
error: 6.10352e-05 
error: 3.05176e-05 
error: 1.52588e-05 
error: 7.62939e-06 
error: 3.8147e-06 
error: 1.90735e-06 
error: 9.53674e-07 
error: 4.76837e-07 
error: 2.38419e-07 
error: 1.19209e-07 
error: 5.96046e-08 
Precision Float: 24 

Auf der Wiki gibt es 2 Antworten für Floats. Der erste ist 1.19209e-07 mit einer Genauigkeit von 23, und der andere ist 5.96046e-08 mit einer Genauigkeit von 24.

Ich sehe beide Antworten genau dort, also weiß ich, dass ich auf dem richtigen Weg bin. Ich verstehe jedoch nicht, warum mein rekursiver Algorithmus das Problem noch einmal unterteilt. Ich glaube, dass die Antwort, die ich suche, 5.96046e-08 oder 1.19209e-07 ist, wenn ich es mit 2 multipliziere. Jedoch bin ich nicht sicher, was mit meinem Code falsch ist, warum es noch einmal ausführt.

Das andere Problem, das ich habe, ist dieses Stück Code funktioniert nicht mit Doubles aus irgendeinem Grund. Also ich würde gerne wissen, warum das so ist. Ist es besser, dies einfach in eine While-Schleife zu werfen und zu sehen, ob sich etwas ändert? Oder habe ich die Formel falsch für Maschine Epsilon?

Jede Hilfe wäre willkommen.

Edit: kompilierten Code hinzugefügt.

EDIT 2: Ich löste mein erstes Problem, der Fehler wurde noch berechnet, ich warf einfach das Stück Code in die else-Anweisung und jetzt berechnet es Gleitkommazahlen ganz gut. Wenn ich jedoch alle Typen in Doubles umwandele, segeln sie Fehler, ich habe keine Ahnung, warum das so ist.

+2

Wenden Sie das übliche Debugging-Verfahren zum Hinzufügen weiterer Ausdrucke oder zum schrittweisen Durchlaufen Ihres Codes an. Es ist auch hier Standard, ein vollständiges Programm einzuschließen, das ausgeschnitten und in eine Datei eingefügt und kompiliert werden kann. –

+0

@KhouriGiordano Ich habe jetzt einen Schnitt gemacht, ich habe die Header-Datei und main.cpp-Datei hinzugefügt. Ich bin mit einem Debugger durch den Code gegangen. Die if-Anweisung macht genau das, was sie tun soll, wenn sie diesen Code ausführt. Es ist jedoch nicht genau gleich 1 in der 24. Iteration. Es entspricht etwa 0.9999981, also geht es zurück in den rekursiven Code und wenn es noch einmal ausgeführt wird, teilt es es unweigerlich erneut und fügt 1 hinzu. Belassen Sie meinen Fehler als 0 und meine Iterationen als 25. – Sailanarmo

+1

Ist das nicht nur ein logischer Fehler? Sie setzen die Genauigkeit auf "n" in dem Moment, in dem "error = 0" ist. Aber "error = 0" auch für jedes "n" größer als das. Ich denke, dass die Genauigkeit der letzte Wert für "n" ist, für den "error! = 0": "epsilon" ist die kleinste Potenz von "2", die zu "1" addiert werden kann, so dass das Ergebnis von "1" unterschieden werden kann '. – Walter

Antwort

0

Ich habe die Antwort auf mein Problem gefunden.

Ich habe meine Funktion geändert, um den Fehler in der else-Anweisung zu berechnen. Auf diese Weise würde es mir jetzt eher den Fehler geben als danach.

Ich löste die Seg Fault mit der Double-Variable, weil ich nicht erkannte, dass (1 < < n) konnte nur 32-mal aufgrund der Größe oder tatsächliche Architektur meiner Maschine verschoben werden. Nach der 32-Iteration der Rekursion würde es also Zufallszahlen ausgeben, die schließlich durch Null dividiert werden und einen Segmentierungsfehler verursachen. Der Code sieht nun so aus:

int MacEpsFloat::precision(int n) 
{ 
    y = 1 - (x/(std::pow(2,n))); 

    if (y == 1.0) 
    { 
     prec = n-1; 
    } 
    else 
    { 
     double error = std::abs(e - y); 
     std::cout << "Error: " << error << std::endl; 
     ++n; 
     precision(n); 
    } 
    return prec; 
} 

Ich habe nicht realisiert, dass ich bisher nur wenig verschieben konnte. Danke für alle, die geholfen haben!