Problem with square root of (2147483647) in c++ - c++

I am calculating square root of 2147483647 by sqrt function.and the result must be a float value 46340.95 but my code returns the value 46341.
Can anyone tell me where is the problem?
i am using code :
double x=2147483647.0;
double y=sqrt(x);
cout<< y;

I get that same result. But, if I inject a setprecision, I get the right value:
#include <iostream>
#include <iomanip>
#include <cmath>
int main (void) {
double x=2147483647.0;
double y=sqrt(x);
std::cout << std::setprecision(10) << y << std::endl;
return 0;
}
gives me:
46340.95
In fact, if you use the folowing code:
#include <iostream>
#include <iomanip>
#include <cmath>
int main (void) {
double x=2147483647.0;
double y=sqrt(x);
std::cout << y << std::endl;
std::cout << std::setprecision(0) << std::fixed << y << std::endl;
std::cout << std::setprecision(1) << std::fixed << y << std::endl;
std::cout << std::setprecision(2) << std::fixed << y << std::endl;
std::cout << std::setprecision(3) << std::fixed << y << std::endl;
return 0;
}
you get:
46341
46341
46341.0
46340.95
46340.950
So it appears that the default setting (at least for my environment) is a precision of zero.
If you want a specific format, I suggest you explicitly request it.

The default precision for cout is not sufficient to show the fractional part of your result. Your result is 46340.95, which rounded to six digits of precision is 43641.0, and is displayed as 43641 by cout. To show more precision, set the precision of cout first:
double x=2147483647.0;
double y=sqrt(x);
cout.precision(9);
cout<< y;
On my system this shows a result of 46340.95.

This trivial code yields 46340.9:
#include <cmath>
#include <iostream>
int main()
{
float x = std::sqrt(2147483647);
std::cout << x << std::endl;
return 0;
}
What does your code look like?
(Just for the record: tested using GCC (g++) 4.5.2 on MacOS X 10.6.6.)

Related

C++ not rounding as it should when using both cout and printf

I need to make a program that calculates cos(x) and my problem is that when I use printf for example cos(0.2) is 0.98 but it comes out as 0.984 and it's not rounding to 2 numbers.
My code:
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
float x = 0.2;
cout << "x=" << x << " cos(y) y=" << printf("%.2f", cos(x)) << "\n";
return 0;
}
The problem is not with rounding the numbers, but with output.
cout << "x=" << x << " cos(y) y=" << printf("%.2f", cos(x)) << "\n";
Here you are mixing two ways to write to the standard output. Inserting a call to printf into cout << will output the return value of printf which happens to be 4 and at the same time output something as a side effect.
So two outputs are created:
Streaming values into cout outputs x=0.2 cos(y) y=4
Calling printf (correctly) outputs 0.98
It is possible that the two outputs are mingled with each other, creating the impression that the result was 0.984:
x=0.2 cos(y) y= 4
^^^^
0.98
You can use both cout and printf, but you should not confuse the return value of printf with the output it creates as a side effect:
cout << "x=" << x << " cos(y) y=";
printf("%.2f\n", cos(x));
should output
x=0.2 cos(y) y=0.98
See also: C++ mixing printf and cout
As others have said in the comments, mixing std::cout and printf does not do what you want. Instead use the stream manipulators std::fixed and std::setprecision:
#include <iomanip> //Required for std::fixed and std::precision
#include <iostream>
#include <cmath> //Notice corrected include, this is the C++ version of <math.h>
using namespace std;
int main()
{
float x = 0.2f; //Initialize with a float instead of silently converting from a double to a float.
cout << "x=" << x << " cos(y) y=" << std::fixed << std::setprecision(2) << cos(x) << "\n";
return 0;
}

Issue with fmod with doubles

It would seem fmod(x,1) where x is a double gives the wrong result, as output by the line:
std::cout << fmod(min, 1) << "|" << fmod(max, 1) << std::endl;
I forgot the name for what you call this, but this is the smallest amount of code necessary to illustrate my problem:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <time.h>
#include <math.h>
const int deviation = 3;
void weightedRandomNumber(double min, double max);
int main() {
srand(time(nullptr));
std::cout.precision(16);
std::cout << 123.1 << "|" << 2789.3234 << std::endl;
weightedRandomNumber(123.1, 2789.3234);
system("pause");
return 0;
}
void weightedRandomNumber(double min, double max) {//inclusive
int multiplier = 1;
std::cout << min << "|" << max << std::endl;
while (fmod(min, 1) > 0 || fmod(max, 1) > 0) {
std::cout << min << "|" << max << std::endl;
std::cout << fmod(min, 1) << "|" << fmod(max, 1) << std::endl;
min *= 10;
max *= 10;
multiplier++;
}
std::cout << min << "|" << max << std::endl;
std::cout << multiplier << std::endl;
}
The outputs I get when I run the code are as such:
123.1|2789.3234
123.1|2789.3234
123.1|2789.3234
0.09999999999999432|0.3234000000002197
1231|27893.234
0|0.2340000000040163
12310|278932.34
0|0.3400000000256114
123100|2789323.4
0|0.400000000372529
1231000|27893234
0|3.725290298461914e-09
12310000|278932340.0000001
0|5.960464477539063e-08
123100000|2789323400
0|4.76837158203125e-07
1231000000|27893234000
0|3.814697265625e-06
12310000000|278932340000.0001
0|6.103515625e-05
123100000000|2789323400000
0|0.00048828125
1231000000000|27893234000000
0|0.00390625
12310000000000|278932340000000
0|0.03125
123100000000000|2789323400000001
0|0.5
1231000000000000|2.7893234e+16
14
Other than this I don't quite know what to say, if I have missed anything necessary please comment so I can amend my question.
The issue is not with fmod, which is giving the highest precision results it can. The issue is with cout precision not behaving like you expect, combined with "rounding" because a double cannot store 0.1 accurately enough to represent what cout considers a precision of 16.
This code demonstrates the issue. The rounding actually occurs when you assign 123.1 to a double, but because of the 3 digits to the left is not visible until it becomes a smaller number.
int main() {
std::cout.precision(16);
std::cout << (123.1L - 123L);
}
output:
0.09999999999999432
Actually....this illustrates the problem even more succinctly:
int main() {
std::cout.precision(20);
std::cout << 123.1;
}
123.09999999999999432
Further reading from the comments on your question:
Is floating point math broken?
Also, for the vast majority of scenarios, a double is more than fine. For accurate, recursive math, you'd want to consider a heavy-duty math library, or even a math-specialized language.
Further further reading:
http://www.boost.org/doc/libs/1_62_0/libs/math/doc/html/math_toolkit/high_precision/why_high_precision.html

A loss of precision

If I have a double string which is equal to "123.546123" and convert it to a double with atof, I get only 123.546. What can I do to fix this?
Here is my code:
#include <iostream>
int main(){
std::string a = "123.546123";
double b = atof(a.c_str());
std::cout << a << std::endl;
std::cout << b << std::endl;
return EXIT_SUCCESS;
}
std::cout prints floating-point values with a precision of 6 by default. To increase that precision, use std::setprecision from <iomanip>, e.g.:
std::cout << std::setprecision(9) << b << std::endl;

How to implement serialization and de-serialization of a double?

I am trying to solve the relatively simple problem of being able to write a double to a file and then to read the file into a double again. Based on this answer I decided to use the human readable format.
I have successfully circumvented the problems some compilers have with nan and [-]infinity according to this question. With finite numbers I use the std::stod function to convert the string representation of a number into the number itself. But from time to time the parsing fails with numbers close to zero, such as in the following example:
#include <cmath>
#include <iostream>
#include <sstream>
#include <limits>
const std::size_t maxPrecision = std::numeric_limits<double>::digits;
const double small = std::exp(-730.0);
int main()
{
std::stringstream stream;
stream.precision(maxPrecision);
stream << small;
std::cout << "serialized: " << stream.str() << std::endl;
double out = std::stod(stream.str());
std::cout << "de-serialized: " << out << std::endl;
return 0;
}
On my machine the result is:
serialized: 9.2263152681638151025201733115952403273156653201666065e-318
terminate called after throwing an instance of 'std::out_of_range'
what(): stod
The program has unexpectedly finished.
That is, the number is too close to zero to be properly parsed. At first I thougth that the problem is that this number is denormal, but this doesn't seem to be the case, since the mantissa starts with a 9 and not a 0.
Qt on the other hand has no problems with this number:
#include <cmath>
#include <limits>
#include <QString>
#include <QTextStream>
const std::size_t maxPrecision = std::numeric_limits<double>::digits;
const double small = std::exp(-730.0);
int main()
{
QString string = QString::number(small, 'g', maxPrecision);
QTextStream stream(stdout);
stream.setRealNumberPrecision(maxPrecision);
stream << "serialized: " << string << '\n';
bool ok;
double out = string.toDouble(&ok);
stream << "de-serialized: " << out << '\n' << (ok?"ok":"not ok") << '\n';
return 0;
}
Outputs:
serialized: 9.2263152681638151025201733115952403273156653201666065e-318
de-serialized: 9.2263152681638151025201733115952403273156653201666065e-318
ok
Summary:
Is this a bug in the gcc implementation of standard library?
Can I circumvent this elegantly?
Should I just use Qt?
Answering question #2:
This is probably my "C-way" kind of thinking, but you could copy the double into a uint64_t (mem-copying, not type-casting), serialize the uint64_t instead, and do the opposite on de-serialization.
Here is an example (without even having to copy from double into uint64_t and vice-versa):
uint64_t* pi = (uint64_t*)&small;
stringstream stream;
stream.precision(maxPrecision);
stream << *pi;
cout << "serialized: " << stream.str() << endl;
uint64_t out = stoull(stream.str());
double* pf = (double*)&out;
cout << "de-serialized: " << *pf << endl;
Please note that in order to avoid breaking strict-aliasing rule, you actually do need to copy it first, because the standard does not impose the allocation of double and uint64_t to the same address-alignment:
uint64_t ismall;
memcpy((void*)&ismall,(void*)&small,sizeof(small));
stringstream stream;
stream.precision(maxPrecision);
stream << ismall;
cout << "serialized: " << stream.str() << endl;
ismall = stoull(stream.str());
double fsmall;
memcpy((void*)&fsmall,(void*)&ismall,sizeof(small));
cout << "de-serialized: " << fsmall << endl;
If you're open to other recording methods you can use frexp:
#include <cmath>
#include <iostream>
#include <sstream>
#include <limits>
const std::size_t maxPrecision = std::numeric_limits<double>::digits;
const double small = std::exp(-730.0);
int main()
{
std::stringstream stream;
stream.precision(maxPrecision);
int exp;
double x = frexp(small, &exp);
//std::cout << x << " * 2 ^ " << exp << std::endl;
stream << x << " * 2 ^ " << exp;
int outexp;
double outx;
stream.seekg(0);
stream >> outx;
stream.ignore(7); // >> " * 2 ^ "
stream >> outexp;
//std::cout << outx << " * 2 ^ " << outexp << std::endl;
std::cout << small << std::endl << outx * pow(2, outexp) << std::endl;
return 0;
}

How to output with 3 digits after the decimal point with C++ stream?

Given a variable of float type, how to output it with 3 digits after the decimal point, using iostream in C++?
Use setf and precision.
#include <iostream>
using namespace std;
int main () {
double f = 3.14159;
cout.setf(ios::fixed,ios::floatfield);
cout.precision(3);
cout << f << endl;
return 0;
}
This prints 3.142
This one does show "13.142"
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
double f = 13.14159;
cout << fixed;
cout << setprecision(3) << f << endl;
return 0;
}
You can get fixed number of fractional digits (and many other things) by using the iomanip header. For example:
#include <iostream>
#include <iomanip>
int main() {
double pi = 3.141592653589;
std::cout << std::fixed << std::setprecision(2) << pi << '\n';
return 0;
}
will output:
3.14
Note that both fixed and setprecision change the stream permanently so, if you want to localise the effects, you can save the information beforehand and restore it afterwards:
#include <iostream>
#include <iomanip>
int main() {
double pi = 3.141592653589;
std::cout << pi << '\n';
// Save flags/precision.
std::ios_base::fmtflags oldflags = std::cout.flags();
std::streamsize oldprecision = std::cout.precision();
std::cout << std::fixed << std::setprecision(2) << pi << '\n';
std::cout << pi << '\n';
// Restore flags/precision.
std::cout.flags (oldflags);
std::cout.precision (oldprecision);
std::cout << pi << '\n';
return 0;
}
The output of that is:
3.14159
3.14
3.14
3.14159
If you want to print numbers with precision of 3 digits after decimal, just add the following thing before printing the number cout << std::setprecision(3) << desired_number. Don't forget to add #include <iomanip> in your code.
In general, precision is the maximum number of digits displayed. The manipulator fixed will set up the output stream for displaying values in fixed format. In fixed the precision is the number of digits after the decimal point. The setprecision allows setting the precision used for displaying floating-point values, it takes an integer argument.
cout << fixed;
cout << setprecision(3) << f << endl;
You may unset fixed using cout.unsetf(ios::fixed)