Je veux contrôler la précision d'un double lors d'une comparaison, puis revenir à la précision par défaut, en C++.
J'ai l'intention d'utiliser setPrecision()
pour définir la précision. Quelle est alors la syntaxe, le cas échéant, pour rétablir la précision par défaut?
Je fais quelque chose comme ça
std::setPrecision(math.log10(m_FTOL));
Je fais des choses, et j'aimerais revenir à la double comparaison par défaut immédiatement après.
J'ai modifié comme ça, et j'ai encore des erreurs
std::streamsize prec = std::ios_base::precision();
std::setprecision(cmath::log10(m_FTOL));
avec cmath
false lors de la compilation, et std::ios_base
également lors de la compilation. Pourriez-vous aider?
Merci.
Vous pouvez obtenir la précision avant vous la changez, avec std::ios_base::precision
, puis utilisez-la pour revenir plus tard.
Vous pouvez voir cela en action avec:
#include <ios>
#include <iostream>
#include <iomanip>
int main (void) {
double d = 3.141592653589;
std::streamsize ss = std::cout.precision();
std::cout << "Initial precision = " << ss << '\n';
std::cout << "Value = " << d << '\n';
std::cout.precision (10);
std::cout << "Longer value = " << d << '\n';
std::cout.precision (ss);
std::cout << "Original value = " << d << '\n';
std::cout << "Longer and original value = "
<< std::setprecision(10) << d << ' '
<< std::setprecision(ss) << d << '\n';
std::cout << "Original value = " << d << '\n';
return 0;
}
qui produit:
Initial precision = 6
Value = 3.14159
Longer value = 3.141592654
Original value = 3.14159
Longer and original value = 3.141592654 3.14159
Original value = 3.14159
Le code ci-dessus montre deux manières de régler la précision, d'abord en appelant std::cout.precision (N)
et en utilisant un manipulateur de flux std::setprecision(N)
.
Mais vous devez garder à l'esprit que la précision concerne la sortie de valeurs via des flux, elle n'affecte pas directement les comparaisons des valeurs elles-mêmes avec un code tel que:
if (val1== val2) ...
En d'autres termes, même si output peut être 3.14159
, la valeur elle-même reste le 3.141592653590
complet (sous réserve des limitations normales en virgule flottante, bien sûr).
Si vous voulez faire cela, vous devrez vérifier si c'est assez proche plutôt qu'égal, avec un code tel que:
if ((fabs (val1 - val2) < 0.0001) ...
Vous devez garder une trace de votre précision actuelle, puis revenir à la même chose une fois vos opérations effectuées avec la précision modifiée requise. Pour cela, vous pouvez utiliserstd :: ios_base :: precision:
streamsize precision ( ) const;
streamsize precision ( streamsize prec );
La première syntaxe renvoie la valeur du champ de précision de virgule flottante en cours pour le flux.
La deuxième syntaxe lui attribue également une nouvelle valeur.
setprecision () peut être utilisé uniquement pour les opérations de sortie et ne peut pas être utilisé pour les comparaisons
Pour comparer les flottants dites a et b, vous devez le faire explicitement comme ceci:
if( abs(a-b) < 1e-6) {
}
else {
}
Sauvegarde l'état complet avec std::ios::copyfmt
Vous voudrez peut-être aussi restaurer l’ensemble de l’état précédent avec std::ios::copyfmt
dans ces situations, comme expliqué à: Restaurez l’état de std :: cout après sa manipulation
main.cpp
#include <iomanip>
#include <iostream>
int main() {
constexpr float pi = 3.14159265359;
constexpr float e = 2.71828182846;
// Sanity check default print.
std::cout << pi << std::endl;
std::cout << e << std::endl;
// Change precision and restore default afterwards.
std::ios cout_state(nullptr);
cout_state.copyfmt(std::cout);
std::cout << std::setprecision(10);
std::cout << pi << std::endl;
std::cout << e << std::endl;
std::cout.copyfmt(cout_state);
// Check that cout state was restored.
std::cout << pi << std::endl;
std::cout << e << std::endl;
}
Compiler et exécuter:
g++ -o main.out -std=c++11 main.cpp
./main.out
Sortie:
3.14159
2.71828
3.141592741
2.718281746
3.14159
2.71828
Testé sur Ubuntu 16.04, GCC 6.4.0.