Set back default floating point print precision in C++

后端 未结 5 630
夕颜
夕颜 2020-11-30 07:45

I want to control the precision for a double during a comparison, and then come back to default precision, with C++.

I intend to use setPrecision() to s

相关标签:
5条回答
  • 2020-11-30 08:00

    You need to keep track of your current precison and then reset back to the same once done with your operations with required modified precison. For this you can use std::ios_base::precision:

    streamsize precision ( ) const;
    streamsize precision ( streamsize prec );
    

    The first syntax returns the value of the current floating-point precision field for the stream.
    The second syntax also sets it to a new value.

    0 讨论(0)
  • 2020-11-30 08:02

    You can get the precision before you change it, with std::ios_base::precision and then use that to change it back later.

    You can see this in action with:

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

    which outputs:

    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
    

    The code above shows two ways of setting the precision, first by calling std::cout.precision (N) and second by using a stream manipulator std::setprecision(N).


    But you need to keep in mind that the precision is for outputting values via streams, it does not directly affect comparisons of the values themselves with code like:

    if (val1== val2) ...
    

    In other words, even though the output may be 3.14159, the value itself is still the full 3.141592653590 (subject to normal floating point limitations, of course).

    If you want to do that, you'll need to check if it's close enough rather than equal, with code such as:

    if ((fabs (val1 - val2) < 0.0001) ...
    
    0 讨论(0)
  • 2020-11-30 08:05

    You can use cout << setprecision(-1)

    0 讨论(0)
  • 2020-11-30 08:13

    Save the entire state with std::ios::copyfmt

    You might also want to restore the entire previous state with std::ios::copyfmt in these situations, as explained at: Restore the state of std::cout after manipulating it

    main.cpp

    #include <iomanip>
    #include <iostream>
    
    int main() {
        constexpr float pi = 3.14159265359;
        constexpr float e  = 2.71828182846;
    
        // Sanity check default print.
        std::cout << "default" << std::endl;
        std::cout << pi << std::endl;
        std::cout << e  << std::endl;
        std::cout << std::endl;
    
        // Change precision format to scientific,
        // and restore default afterwards.
        std::cout << "modified" << std::endl;
        std::ios cout_state(nullptr);
        cout_state.copyfmt(std::cout);
        std::cout << std::setprecision(2);
        std::cout << std::scientific;
        std::cout << pi << std::endl;
        std::cout << e  << std::endl;
        std::cout.copyfmt(cout_state);
        std::cout << std::endl;
    
        // Check that cout state was restored.
        std::cout << "restored" << std::endl;
        std::cout << pi << std::endl;
        std::cout << e  << std::endl;
        std::cout << std::endl;
    }
    

    GitHub upstream.

    Compile and run:

    g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
    ./main.out
    

    Output:

    default
    3.14159
    2.71828
    
    modified
    3.14e+00
    2.72e+00
    
    restored
    3.14159
    2.71828
    

    Tested on Ubuntu 19.04, GCC 8.3.0.

    Use C++20 std::format and {:.2} instead of std::setprecision

    Finally, this will be the superior choice once you can use it:

    #include <format>
    #include <string>
    
    int main() {
        std::cout << std::format("{:.2} {:.3}\n", 3.1415, 3.1415);
    }
    

    Expected output:

    3.14 3.145
    

    This will therefore completely overcome the madness of modifying std::cout state.

    More information at: std::string formatting like sprintf

    0 讨论(0)
  • 2020-11-30 08:21

    setprecision() can be used only for output operations and cannot be used for comparisons

    To compare floats say a and b , you have to do it explicitly like this:

      if( abs(a-b) < 1e-6) {   
      }
      else {
      } 
    
    0 讨论(0)
提交回复
热议问题