How to Specify Setprecision Rounding

How to specify setprecision rounding

There is also std::fesetround from <cfenv>, which sets the rounding direction:

#include <iostream>
#include <iomanip>
#include <cmath>
#include <cfenv>

int main () {
double runtime = 0.756247615801;

// Set rounding direction and output with some precision:
const auto prev_round = std::fegetround();
std::fesetround(FE_DOWNWARD);
std::cout << "desired: " << std::setprecision(6) << runtime << "\n";

// Restore previous rounding direction and output for testing:
std::fesetround(prev_round);
std::cout << "default: " << std::setprecision(6) << runtime << "\n";
}

(note that these are not the kind of comments I recommend, they are just for tutoring purposes)

Output:

desired: 0.756247
default: 0.756248

Important note, though: I did not find any mention in the standard, that the operator<< overloads for floating types have to honour the rounding direction.

Does setprecision in c++ round? If so why am I seeing this?

The number 0.298475 isn't representable exactly in a double (since it's not a fraction whose denominator is a power of two, being 11939/40000), and the actual number that is stored is actually closer to 0.29847 than to 0.29848.

Why is not the output precision being rounded correctly?

The comment tells you why. I strongly recommend to read https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

In order to do correct rounding, C++ comes with round() for that but it only round to integer, not arbitrary decimal places. The following can give you 1.235, although a bit ugly:

double f1 = 3.1415;
std::cout << std::setprecision(4) << round(f1*1000)/1000 << '\n';
double f2 = 1.2345;
std::cout << std::setprecision(4) << round(f2*1000)/1000 << '\n';

C++ rounding behavior

Your computer can't represent most decimal fractions numbers exactly, since it works with binary numbers. Instead, it tries to find the closest number it can represent, and use that instead.

For instance, my computer represents the following numbers as:

decimal      actual representation
0.115 0.115000002
0.225 0.224999994
0.245 0.245000005
0.335 0.335000008
0.445 0.444999993

By default, C++ will use normal rounding to closest, i.e., digits 5-9 are rounded up and 0-4 are rounded down. Therefore, of the numbers above, 0.115, 0.245 and 0.335 will be rounded up to 0.12, 0.24 and 0.34, while 0.225 and 0.445 will be rounded down to 0.22 and 0.44.

C/C++ rounding up decimals with a certain precision, efficiently

I wrote an integer square root subroutine with nothing more than a couple dozen lines of ASM, with no API calls whatsoever - and it still could only do about 50 million SqRoots/second (this was about five years ago ...).

The point I'm making is that if you're going for billions of calls, even today's technology is going to choke.

But if you really want to make an effort to speed it up, remove as many API usages as humanly possible. This may require you to perform API tasks manually, instead of letting the libraries do it for you. Specifically, remove any type of stream operation. Those are slower than dirt in this context. You may really have to improvise there.

The only thing left to do after that is to replace as many lines of C++ as you can with custom ASM - but you'll have to be a perfectionist about it. Make sure you are taking full advantage of every CPU cycle and register - as well as every byte of CPU cache and stack space.

You may consider using integer values instead of floating-points, as these are far more ASM-friendly and much more efficient. You'd have to multiply the number by 10^7 (or 10^p, depending on how you decide to form your logic) to move the decimal all the way over to the right. Then you could safely convert the floating-point into a basic integer.

You'll have to rely on the computer hardware to do the rest.

<--Microsoft Specific-->
I'll also add that C++ identifiers (including static ones, as Donnie DeBoer mentioned) are directly accessible from ASM blocks nested into your C++ code. This makes inline ASM a breeze.

<--End Microsoft Specific-->

set precision c#

This is a fundamental limitation of floating point types.. double is actually store internally as a sign exponent and mantissa, the exponent is base 2, so has a lot of trouble dealing with base 10..

The easiest solution is to use a base 10 64bit floating point type, namely decimal. Its still floating point, it still only limited precision but it is a lot friendly and more accurate to work with in a lot of cases

Update

If all you want to do is change the display output, you can either use rounding (which you know), or the appropriate format specifiers with string.format ToString or string interpolation

Example

var number = 5.123455123321321;
Console.WriteLine(number.ToString("F3",
CultureInfo.InvariantCulture));
Console.WriteLine($"{number:F3}");
// Displays 5.123
// Displays 5.123


Related Topics



Leave a reply



Submit