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
How to Std::Move Objects Out of Functions? (C++11)
Passing Shared Pointers as Arguments
Differencebetween Wm_Quit, Wm_Close, and Wm_Destroy in a Windows Program
Are C++ Templates Just MACros in Disguise
Pure Virtual Functions May Not Have an Inline Definition. Why
Passing Rvalues Through Std::Bind
C++ Undefined Reference to Vtable and Inheritance
Undefined Reference to '_Stack_Chk_Fail'
I Want a Vector of Derived Class Pointers as Base Class Pointers
Visual Studio Code Formatting for "{ }"
Fast Fixed Point Pow, Log, Exp and Sqrt
How Much Footprint Does C++ Exception Handling Add
Console Output in a Qt Gui App
Expand File Names That Have Environment Variables in Their Path
Do Class Functions/Variables Have to Be Declared Before Being Used