web-dev-qa-db-fra.com

régler la précision par défaut C++

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.

15
octoback

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) ...
24
paxdiablo

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.

4
Alok Save

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 {
  } 
2
premprakash

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.