Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set back default floating point print precision in C++

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 set precision. What is then syntax, if any, to set precision back to default?

I am doing something like this

std::setPrecision(math.log10(m_FTOL));

I do some stuff, and I would like to come back to default double comparison right afterwards.

I modified like this, and I still have some errors

std::streamsize prec = std::ios_base::precision();
std::setprecision(cmath::log10(m_FTOL));

with cmath false at compilation, and std::ios_base also false at compilation. Could you help?

like image 283
kiriloff Avatar asked Sep 24 '12 07:09

kiriloff


People also ask

How do you set precision to float?

To set the precision in a floating-point, simply provide the number of significant figures (say n) required to the setprecision() function as an argument. The function will format the original value to the same number of significant figures (n in this case).

How do I set precision in printf?

In C, there is a format specifier in C. To print 4 digits after dot, we can use 0.4f in printf().

How do you reset precision in CPP?

You can get the precision before you change it, with std::ios_base::precision and then use that to change it back later. 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) .

What is precision in C programming?

Precision determines the accuracy of the real numbers and is denoted by the dot (.) symbol. The Exactness or Accuracy of real numbers is indicated by the number of digits after the decimal point. So, precision means the number of digits mentioned after the decimal point in the float number.


3 Answers

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) ...
like image 166
paxdiablo Avatar answered Oct 23 '22 14:10

paxdiablo


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("{:.3} {:.4}\n", 3.1415, 3.1415);
}

Expected output:

3.14 3.145

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

The existing fmt library implements it for before it gets official support: https://github.com/fmtlib/fmt Install on Ubuntu 22.04:

sudo apt install libfmt-dev

Modify source to replace:

  • <format> with <fmt/core.h>
  • std::format to fmt::format

main.cpp

#include <iostream>

#include <fmt/core.h>

int main() {
    std::cout << fmt::format("{:.3} {:.4}\n", 3.1415, 3.1415);
}

and compile and run with:

g++ -std=c++11 -o main.out main.cpp -lfmt
./main.out

Output:

3.14 3.142

See also:

  • How do I print a double value with full precision using cout?
  • std::string formatting like sprintf

Pre C++20/fmt::: 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.


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.

like image 5
Alok Save Avatar answered Oct 23 '22 14:10

Alok Save