2017-09-03 1 views
0

J'essaie de trouver la précision et l'erreur pour la Machine Epsilon. Sans utiliser std :: numeric_limits. J'ai reçu la formule suivante par mon professeur y = 1-x/2^n, n> 1. Je suppose que y est la Machine Epsilon, x est 1.0, et n devrait être la précision.Machine Epsilon Erreur de calcul en C++

Voici mon fichier d'en-tête 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; 
}; 

Voici mon fichier macEpsFloat.cpp

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; 
} 

est ici main.cpp

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


int main() 
{ 

    MacEpsFloat a; 

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

} 

La variable y est set égal à 1.0, e est égal à 1.0, et n est égal à 1.

-je obtenir la sortie suivante:

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 

Sur le Wiki il y a 2 réponses pour Flotteurs. Le premier est 1.19209e-07 avec une précision de 23, et l'autre est 5.96046e-08 avec une précision de 24.

Je vois les deux réponses là, donc je sais que je suis sur la bonne voie. Cependant, je ne comprends pas pourquoi mon algorithme récursif divise le problème une fois de plus. Je crois que la réponse que je cherche est 5.96046e-08, ou 1.19209e-07 si je la multiplie par 2. Cependant, je ne suis pas sûr de ce qui ne va pas avec mon code sur pourquoi il s'exécute une fois de plus.

L'autre problème que je rencontre est que ce morceau de code ne fonctionne pas avec des doubles pour une raison quelconque. Donc j'aimerais savoir pourquoi c'est. Est-il préférable de simplement jeter ceci dans une boucle while et de voir si quelque chose change? Ou ai-je la mauvaise formule pour Machine Epsilon?

Toute aide serait appréciée.

Modifier: ajout de code compilé. J'ai résolu mon problème initial, l'erreur était encore en cours de calcul, j'ai simplement jeté le morceau de code dans l'instruction else et maintenant il calcule des points flottants très bien. Cependant, quand je change tous les types en doubles, ça fait des failles, je ne sais pas pourquoi ça fait ça.

+2

Appliquez la procédure de débogage habituelle consistant à ajouter davantage d'impressions ou à parcourir votre code. Il est également standard ici d'inclure un programme complet qui peut être coupé et collé dans un fichier et compilé. –

+0

@KhouriGiordano J'ai maintenant fait une modification, j'ai ajouté le fichier d'en-tête et le fichier main.cpp. J'ai traversé le code avec un débogueur. L'instruction if fait exactement ce qu'elle devrait faire lors de l'exécution de ce code. Cependant, il n'est pas exactement égal à 1 sur la 24ème itération. Cela équivaut à quelque chose comme 0.9999981, donc ça revient dans le code récursif et quand il est exécuté 1 fois de plus, il le divise inévitablement et lui ajoute 1. Laisser mon erreur à 0 et mes itérations à 25. – Sailanarmo

+1

N'est-ce pas une erreur logique? Vous définissez la précision à 'n' au moment où' error = 0'. Mais 'error = 0' aussi pour chaque' n' plus grand que cela. Je pense que la précision est la dernière valeur de 'n' pour laquelle' error! = 0': 'epsilon' est la plus petite puissance de' 2' qui peut être ajoutée à '1' de sorte que le résultat puisse être distingué de' 1 '. – Walter

Répondre

0

J'ai trouvé la réponse à mon problème.

J'ai changé ma fonction pour calculer l'erreur dans l'instruction else. De cette façon, cela me donnerait l'erreur actuellement plutôt qu'après. J'ai résolu le Seg Fault avec la variable Double parce que je ne savais pas que (1 < < n) ne pouvait être déplacé 32 fois en raison de la taille, ou l'architecture réelle de ma machine. Donc, après l'itération de la récursion, il rejetterait des nombres aléatoires, éventuellement en les divisant par zéro, provoquant une erreur de segmentation. Le code ressemble maintenant à ceci:

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; 
} 

Je n'avais pas réalisé que je ne pouvais que peu décaler jusqu'à maintenant. Merci à tous ceux qui ont aidé!