0

J'écris un morceau de code pour convertir des valeurs doubles en notations scientifiques jusqu'à une précision de 15 en C++. Je sais que je peux utiliser des librairies standards comme sprintf avec l'option% e pour le faire. Mais je devrais sortir avec ma propre solution. J'essaie quelque chose comme ça.double à la conversion de notation scientifique - erreur de précision

double norm = 68600000; 
if (norm) 
{ 
    while (norm >= 10.0) 
    { 
     norm /= 10.0; 
     exp++; 
    } 
    while (norm < 1.0) 
    { 
     norm *= 10.0; 
     exp--; 
    } 
} 

Le résultat que je reçois est

norm = 6.8599999999999994316; 
exp = 7 

La raison de perdre cette précision, je clarifiais de ce question

Maintenant, j'essaie d'arrondir la valeur à la précision de 15, qui résulterait dans

6.859 999 999 999 999

(son évident que depuis le 16e point décimal est inférieur à 5 nous obtenons ce résultat)

Réponse attendue: norm = 6,860 000 000 000 000, exp = 7

Ma question est, est-il une meilleure façon pour le double à la notation de notation scientifique à la précision de 15 (sans utiliser les libs standard), de sorte que j'obtiendrais exactement 6.86 quand je l'arrondirai. Si vous avez remarqué le problème ici est pas avec le mécanisme d'arrondi, mais avec le double à la conversion de la notation scientifique due à la perte de précision liée à la machine epsilon

+0

Votre norme initiale sera toujours un nombre entier? – Hayden

+0

Non Il peut également s'agir de valeurs décimales. – vibz

Répondre

2

Vous pouvez déclarer la norme comme un long double pour une plus grande précision. long double wiki Bien qu'il existe des problèmes spécifiques au compilateur à connaître. Certains compilateurs font longtemps double avec double.

Une autre façon de résoudre ce problème de précision est de travailler avec des nombres sous la forme de chaînes et d'implémenter des opérations arithmétiques personnalisées pour les chaînes qui ne seraient pas soumises à la machine epsilon. Par exemple:

int getEXP(string norm){ return norm.length() - 1; }; 

string norm = "68600000"; 
int exp = getEXP(norm); // returns 7 

L'étape suivante consisterait à mettre en œuvre des fonctions pour insérer un caractère décimal dans l'endroit approprié dans la chaîne de norme, et ajouter ce niveau de précision que vous souhaitez. Aucune machine epsilon à s'inquiéter.

+0

Merci à Alex pour cette suggestion. J'ai essayé avec un double long, mais il donne toujours la même erreur de précision à partir de la 15ème décimale. Ne devrait pas donner une meilleure précision car il est de 80 bits, par rapport aux valeurs doubles de 64 bits. – vibz

+0

@vibz vous devez faire l'arrondi au nombre désiré de chiffres vous-même, * après * conversion en double long. Pour certains doubles virgule flottante, la représentation la plus proche sera * inférieure * à la décimale désirée, et le déplacer vers un plus grand conteneur ne va pas changer cela. –

+0

@mark ok je l'ai maintenant :) – vibz