Prevent over-rounding happening in C++ doubles - c++

Have googled a lot about avoiding rounding errors but none of them are solving my case. Need to round off 9.99999975e-05 upto 8 or more precision.
Have tried using stringstream along with setprecision which is pretty much the standard way according to other answers on this site.
#include <iostream>
#include <sstream>
#include <iomanip>
using namespace std;
int main(void){
double val = 9.99999975e-05;
stringstream tmp;
tmp << setprecision(8) << fixed << val;
cout << tmp.str();
return 0;
}
Ideally I would like the result to be 0.00009999
But I am getting 0.00010000 , which I believe is occurring due to rounding off from farthest to most significant '9'.
Any idea how can I stop rounding at 8th precision ?

Need to round off 9.99999975e-05 upto 8 or more precision. (...)
I would like the result to be 0.00009999
Without other test cases I can only guess the OP's intent. So why not truncating the string resulting from the maximum output precision possible?
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <limits>
int main()
{
double val = 9.99999975e-05;
std::stringstream tmp;
tmp << std::setprecision(std::numeric_limits<double>::digits10 + 1)
<< std::fixed << val;
auto repr = tmp.str();
// Truncate the string
repr = repr.erase(repr.find('.') + 9);
std::cout << repr << '\n'; // --> 0.00009999
}
I'll also assume that the OP are already aware of What Every Computer Scientist Should Know About Floating-Point Arithmetic.

Which platform are you using ? You can try using fesetround api in linux and _controlfp in windows.
I get Value 0.000099999998 on linux when rounding set to zero.
However, i will always recommend using a floating point library for such codes.

For the sake of completeness after going through How to truncate a floating point number after a certain number of decimal places (no rounding)? mentioned by #Arne above in comments, here's the changes that I made to above piece of code;
double val = 9.99999975e-05;
cout << setprecision(8) << fixed << trunc(100000000 * val) / 100000000;
return 0;

Related

How do I prevent decimals from rounding off when printed in C++? [duplicate]

This question already has answers here:
How to specify setprecision rounding
(4 answers)
Closed 1 year ago.
I'm doing my ICT homework and I ran into this problem: the decimals keep on getting rounded off when I print them. I've already included the <iomanip> header and used the fixed and setprecision manipulators, but it still keeps getting rounded off. Here's my code:
#include <iostream>
#include <iomanip>
using namespace std;
int main ()
{
double num1 = 3.12345678
cout << fixed << setprecision (4);
cout << num1 << endl;
return 0;
}
When I run the program, "3.1235" comes out instead of "3.1234," which is the expected output according to my teacher. How do I prevent the fourth decimal from rounding off?
Expanding answer of #eerorika. You can use std::fesetround() to set rounding strategy, as in code below. It outputs 3.1234 as you wished. Possible values for this function's argument are FE_DOWNWARD, FE_TONEAREST, FE_TOWARDZERO, FE_UPWARD.
Try it online!
#include <iostream>
#include <iomanip>
#include <cfenv>
int main() {
double num = 3.12345678;
std::fesetround(FE_TOWARDZERO);
std::cout << std::fixed << std::setprecision(4) << num << std::endl;
}
Output:
3.1234
3.1234 is not the expected output, setprecision will round to the specified precision.
One solution to get 3.1234 is to round to the desired number of decimal places yourself (std::trunc just rounds towards zero):
#include <cmath>
...
std::cout << std::fixed << std::setprecision(4);
std::cout << std::trunc(num1 * 10000) / 10000 << endl;
If you want to prevent rounding i.e. you want to see more precision, you can use a higher value with setprecision.
If you want to round towards zero instead of rounding towards nearest, you can use the FE_TOWARDZERO rounding mode.

C++ decimal placement

how would I make it so when i enter 2.785 for the input question the output will display the variable question as 2.79?
I tried using setprecision but for some reason it is not working unless i am doing it wrong
here is the user input question and what it should be:
Enter positive daily growth % (.1 must be entered as 10):
user enters "2.785"
output -> 0.02785
My desired output should look like:
desired output-> 2.79%
Any help is appreciated. I know it may seem simple to others but I have already tried looking online and everything I find just isn't making sense or doesn't work and I dont know what I am doing wrong.
Floating point arithmetic
The reason why it is challenging is that floating point cannot be represented accurately when you perform operations on them. See wikipedia article
It is a very intesting topic, if you have a bit of time, take a look at explanations about floating point and how its representation inside the computer.
If you are looking for the display only (only works for small decimals)
If you are just looking to display a small value you can use below code:
#include <cmath>
#include <iostream>
#include <iomanip>
#include <limits>
#include <sstream>
using namespace std;
string truncateAsString(double n, int precision) {
stringstream ss;
double remainder = static_cast<double>((int)floor((n - floor(n)) * precision) % precision);
ss << setprecision(numeric_limits<double> ::max_digits10 + __builtin_ctz(precision))<< floor(n);
if (remainder)
ss << "." << remainder;
cout << ss.str() << "%" << endl;
return ss.str();
}
int main(void) {
double a = 0.02785;
int precision = 100; // as many digits as you add zeroes. 3 zeroes means precision of 3.
string s = truncateAsString(a*100 + 0.5 / 100, precision);
return 0;
}
Looking for the true value?
Maybe you are looking for true value for your floating point, you can use boost multiprecision library
The Boost.Multiprecision library can be used for computations requiring precision exceeding that of standard built-in types such as float, double and long double. For extended-precision calculations, Boost.Multiprecision supplies a template data type called cpp_dec_float. The number of decimal digits of precision is fixed at compile-time via template parameter.
You need to use a custom library like boost/multiprecision because of the lack of precision for floating points, see my code below:
#include <boost/math/constants/constants.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <iostream>
#include <limits>
#include <cmath>
#include <iomanip>
using namespace std;
using boost::multiprecision::cpp_dec_float_50;
cpp_dec_float_50 truncate(cpp_dec_float_50 n, int precision) {
cpp_dec_float_50 remainder = static_cast<cpp_dec_float_50>((int)floor((n - floor(n)) * precision) % precision) / static_cast<cpp_dec_float_50>(precision);
return floor(n) + remainder;
}
int main(void) {
int precision = 100; // as many digits as you add zeroes. 5 zeroes means precision of 5.
cpp_dec_float_50 n = 0.02785 * 100;
n = truncate(n + 0.5/precision, precision); // first part is remainder, floor(n) is int value truncated.
cout << setprecision(numeric_limits<cpp_dec_float_50> ::max_digits10 + __builtin_ctz(precision)) << n << "%" << endl; // __builtin_ctz(precision) will equal the number of trailing 0, exactly the precision we need!
return 0;
}
Output (both cases)
2.79%
NB: I add 0.5 / precision to the truncate function to force it to act like a rounding.

I am trying to solve timus reverse root (1001) problem and facing the following problem

#include <iostream>
#include <cmath>
double buf[128 * 1024];
int main()
{
int i = 0;
unsigned long long n; // 64-bit unsigned integer
while (std::cin>>n) {
buf[i ++] = double(sqrt(n)); // store in buffer
}
i--;
while(i>=0){
printf("%lf\n",buf[i]); // When i am using this it works fine.
//std::cout<<buf[i]<<std::endl; // When i am using this line instead of printf function it shows wrong answer. why?
i--;
}
return 0;
}
I have compiled it with G++.
While I am trying to print the output with printf funtion then it is accepted. But when I am using cout function then it gives wrong answer. Why is it happened?
This code shows compilation error when i am compiling it in GCC7.1 . What is the reason of this?
Problem Link : https://acm.timus.ru/problem.aspx?space=1&num=1001
Using the << operator with std::cout rounds to 6 significant figures by default and uses scientific notation for large floating point numbers. To disable the scientific notation, include the <iomanip> header and use std::cout << std::fixed << buf[i];. Using std::fixed will also set the rounding to 6 digits after the decimal point.

C++ String to double conversion using stringstream gives precision error

This is a snippet of my code. I need some help in removing the error shown below.
#include <iostream>
#include <string>
#include <sstream>
int main()
{
char doubleStr[] = "5.2";
double d = 0.0;
std::stringstream stream (doubleStr);
stream >> d;
std::cout << d << std::endl;
std::cout << (d <= 5.2);
return 0;
}
This gives output:
5.200000000002
0
How to remove this precision error? Can I use std::setprecision() to solve the issue?
numeric_limits<double>::digits10 can be used to find the number of digits that are uniquely representable by a double.
I see you've tagged your question with Visual Studio. You can test this code on http://webcompiler.cloudapp.net/ to get Visual Studio's number of uniquely representable digits for a double:
#include <iostream>
#include <limits>
int main() { std::cout << std::numeric_limits<double>::digits10 << std::endl; }
This code will not output 2 it will output:
15
Which means that any double up to 14 decimal places will survive the round trip through a stringstream and still be equal to itself.
The above means that there is something you are not including in your example that is causing the round trip failure, or you are using non-standard source files that are not IEEE compliant. (For example I can do a live example on gcc that gives a contrary output to yours, and running the same code on Visual Studio disagrees with your output.)
Either way, for any uniquely representable double (like 5.2), you can ensure that round trip success through a stringstream by setting the precision. Precision is a sticky modifier, so you'll only need to set it once after stream construction. In your example you use stringstream stream so before you work with stream you'd need to set this modifier:
stream.precision(numeric_limits<double>::digits10 - 1);
You can use it like this in order to show the double number in the right way:
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <limits>
int main()
{
char doubleStr[] = "5.2";
double d = 0.0;
std::stringstream stream (doubleStr);
stream >> d;
std::cout << std::setprecision(2)<< d << std::endl;
return 0;
}
http://cpp.sh/9lub
about comparing float point numbers you may look at this What is the most effective way for float and double comparison?

avoid rounding error (floating specifically) c++

http://www.learncpp.com/cpp-tutorial/25-floating-point-numbers/
I have been about this lately to review C++.
In general computing class professors tend not to cover these small things, although we knew what rounding errors meant.
Can someone please help me with how to avoid rounding error?
The tutorial shows a sample code
#include <iomanip>
int main()
{
using namespace std;
cout << setprecision(17);
double dValue = 0.1;
cout << dValue << endl;
}
This outputs
0.10000000000000001
By default float is kept 6-digits of precisions. Therefore, when we override the default, and asks for more (n this case, 17!!), we may encounter truncation (as explained by the tutorial as well).
For double, the highest is 16.
In general, how do good C++ programmers avoid rounding error?
Do you guys always look at the binary representation of the number?
Thank you.
The canonical advice for this topic is to read "What Every Computer Scientist Should Know About Floating-Point Arithmetic", by David Goldberg.
In other words, to minimize rounding errors, it can be helpful to keep numbers in decimal fixed-point (and actually work with integers).
#include <iostream>
#include <iomanip>
int main() {
using namespace std;
cout << setprecision(17);
double v1=1, v1D=10;
cout << v1/v1D << endl; // 0.10000000000000001
double v2=3, v2D=1000; //0.0030000000000000001
cout << v2/v2D << endl;
// v1/v1D + v2/v2D = (v1*v2D+v2*v1D)/(v1D*v2D)
cout << (v1*v2D+v2*v1D)/(v1D*v2D) << endl; // 0.10299999999999999
}
Short version - you can't really avoid rounding and other representation errors when you're trying to represent base 10 numbers in base 2 (ie, using a float or a double to represent a decimal number). You pretty much either have to work out how many significant digits you actually have or you have to switch to a (slower) arbitrary precision library.
Most floating point output routines look to see if the answer is very close to being even when represented in base 10 and round the answer to actually be even on output. By setting the precision in this way you are short-circuiting this process.
This rounding is done because almost no answer that comes out even in base 10 will be even (i.e. end in an infinite string of trailing 0s) in base 2, which is the base in which the number is represented internally. But, of course, the general goal of an output routine is to present the number in a fashion useful for a human being, and most human beings in the world today read numbers in base 10.
When you calculate simple thing like variance you can have this kind of problem... here is my solution...
int getValue(double val, int precision){
std::stringstream ss;
ss << val;
string strVal = ss.str();
size_t start = strVal.find(".");
std::string major = strVal.substr(0, start);
std::string minor = strVal.substr(start + 1);
// Fill whit zero...
while(minor.length() < precision){
minor += "0";
}
// Trim over precision...
if(minor.length() > precision){
minor = minor.substr(0, precision);
}
strVal = major + minor;
int intVal = atoi(strVal.c_str());
return intVal;
}
So you will make your calcul in the integer range...
for example 2523.49 became 252349 whit a precision of tow digits, and 2523490 whit a precision of tree digit... if you calculate the mean for example first you convert all value in integer, make the summation and get the result back in double, so you not accumulate error... Error are amplifie whit operation like square root and power function...
You want to use the manipulator called "Fixed" to format your digits correctly so they do not round or show in a scientific notation after you use fixed you will also be able to use set the precision() function to set the value placement to the right of the .
decimal point. the example would be as follows using your original code.
#include <iostream>
#include <iomanip>
int main()
{
using namespace std;
double dValue = 0.19213;
cout << fixed << setprecision(2) << dValue << endl;
}
outputs as:
dValue = 0.19