Why does a1=72 instead of 73 in this (terrible) snippet of C++ code ?
#include <iostream>
#include <string>
using namespace std;
int main (int argc, char* argv[])
{
double a = 136.73;
unsigned int a1 = (100*(a-(int)a));
cout << (a-(int)a) << endl; // 0.73
cout << 100*(a-(int)a) << endl; // 73
cout << a1 << endl; // 72 !
}
You can execute it at http://codepad.org/HhGwTFhw
If you increase the output precision, you'll see that (a - (int) a) prints 0.7299999999999898.
Therefore, the truncation of this value (which you obtain when you cast it to an int) is indeed 72.
(Updated codepad here.)
This is a common precision issue. The literal 136.73 actually stands for the number
136.729999999999989768184605054557323455810546875
and the result of a-(int)a is not 0.73 (even though that is what is displayed), but rather
0.729999999999989768184605054557323455810546875
When you multiply that by 100, you get
72.9999999999989768184605054557323455810546875
And since converting from double to int cuts off everything after the decimal point, you get 72.
0.73 cannot be represented exactly so it is rounded to a number close to it, which in this example is lower then 0.73. when multiplying by 100, you get 72.[something], which is later trimmed to 72.
more info
It might become clear if you read the following article: What Every Computer Scientist Should Know About Floating-Point Arithmetic.
The others have already shown that the result of (a - (int)a) is not exactly 0.73, but a little lower. The article explains why that is so. It is not exactly an easy read, but really something everyone working with FP should read and try to understand, IMO.
Related
I am still quite new in the C++ business.
I want to output a float number with only one decimal number.
At first I thought it would work with Modulo (%), but I quickly discarded this. Then I wanted to solve it calculated, but I couldn't solve this.
There is also a clue. I can only use <iostream> and <fstream>.
But now I came across the function setprecision().
My output code is.
cout<<fixed<<setprecision(2)<<variable<<endl;
However, it outputs e.g. 2.99. I need 2.9 though.
cout<<fixed<<setprecision(1)<<variable<<endl;
Outputs 3.0, though.
Please help me, I will be infinitely grateful. :)
Illustrating the floating-point environment solution from Sebastian in the comments
#include <fenv.h>
#include <iostream>
#include <iomanip>
int main() {
if (fesetround(FE_TOWARDZERO)) {
// need to check for non-zero error condition
std::cerr << "Unable to set correct rounding direction" << std::endl;
return 1;
}
float value = 2.99f;
std::cout << std::setprecision(2) << value << std::endl;
}
This prints
2.9
Note that this will also affect other floating point calculations, which may cause unexpected results.
I don't know how widespread support is for these different rounding directions on different target architectures, so if you want extreme portability you'll need to provide a back up solution if fesetround returns a non-zero value.
godbolt
Here's one way:
#include <math.h>
#include <iostream>
int main() {
auto f = 2.9999;
std::cout << trunc(f * 10) / 10 << '\n';
}
Sebastian solved it in the comments.
cout<< fixed<<setprecision(1)<<variable-.05<<endl;
Thank you all for contributing.
I'll try to improve my
Using the GSL (GNU Scientific Library), I'm trying to understand why gsl_vector_view_array() returns a slighly modified value after assignment.
In the code below, I declare a vector_view 'qview_test' which is linked to table q_test[0]=0.0 and display its value which is 0.0. Then, I change the value of q_test[0]=1.12348 and expecting the same value for qview_test, but it gets alterated to qview_test=1.1234800000000000341771055900608189.
How do you explain such a result ? How to replicate the result without GSL ?
#include <iostream>
#include <gsl/gsl_blas.h>
using namespace std;
double q_test[1]={0.0};
gsl_vector_view qview_test;
int nb_variable = 1;
int main()
{
qview_test=gsl_vector_view_array(q_test,nb_variable);
cout.precision(35);
cout << "qview before: " << gsl_vector_get(&qview_test.vector,0)<< endl;
// Assign value
q_test[0]=1.12348;
cout << "qview after: " << gsl_vector_get(&qview_test.vector,0) << endl;
return 0;
}
Thanks for any help,
H.Nam
This looks like floating point rounding to me.
Basically any decimal number can only have a finite precision and all numbers in between get rounded to the nearest float.
I am not familiar with gsl so I don't know why it's displaying so many digits.
In other words, to get more precise give your number more bits (128 bit float or something like that) to be represented. This will give you more precision, however you most likely won't need it.
#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;
int main() {
int t;
double n;
cin>>t;
while(t--)
{
cin>>n;
double x;
for(int i=1;i<=10000;i++)
{
x=n*i;
if(x==ceilf(x))
{
cout<<i<<endl;
break;
}
}
}
return 0;
}
For I/P:
3
5
2.98
3.16
O/P:
1
If my code is:
#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;
int main() {
int t;
double n;
cin>>t;
while(t--)
{
cin>>n;
double x;
for(int i=1;i<=10000;i++)
{
x=n*i;
cout<<"";//only this statement is added;
if(x==ceilf(x))
{
cout<<i<<endl;
break;
}
}
}
return 0;
}
For the same input O/P is:
1
50
25
The only extra line added in 2nd code is: cout<<"";
Can anyone please help in finding why there is such a difference in output just because of the cout statement added in the 2nd code?
Well this is a veritable Heisenbug. I've tried to strip your code down to a minimal replicating example, and ended up with this (http://ideone.com/mFgs0S):
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
float n;
cin >> n; // this input is needed to reproduce, but the value doesn't matter
n = 2.98; // overwrite the input value
cout << ""; // comment this out => y = z = 149
float x = n * 50; // 149
float y = ceilf(x); // 150
cout << ""; // comment this out => y = z = 150
float z = ceilf(x); // 149
cout << "x:" << x << " y:" << y << " z:" << z << endl;
}
The behaviour of ceilf appears to depend on the particular sequence of iostream operations that occur around it. Unfortunately I don't have the means to debug in any more detail at the moment, but maybe this will help someone else to figure out what's going on. Regardless, it seems almost certain that it's a bug in gcc-4.9.2 and gcc-5.1. (You can check on ideone that you don't get this behaviour in gcc-4.3.2.)
You're probably getting an issue with floating point representations - which is to say that computers cannot perfectly represent all fractions. So while you see 50, the result is probably something closer to 50.00000000001. This is a pretty common problem you'll run across when dealing with doubles and floats.
A common way to deal with it is to define a very small constant (in mathematical terms this is Epsilon, a number which is simply "small enough")
const double EPSILON = 0.000000001;
And then your comparison will change from
if (x==ceilf(x))
to something like
double difference = fabs(x - ceilf(x));
if (difference < EPSILON)
This will smooth out those tiny inaccuracies in your doubles.
"Comparing for equality
Floating point math is not exact. Simple values like 0.2 cannot be precisely represented using binary floating point numbers, and the limited precision of floating point numbers means that slight changes in the order of operations can change the result. Different compilers and CPU architectures store temporary results at different precisions, so results will differ depending on the details of your environment. If you do a calculation and then compare the results against some expected value it is highly unlikely that you will get exactly the result you intended.
In other words, if you do a calculation and then do this comparison:
if (result == expectedResult)
then it is unlikely that the comparison will be true. If the comparison is true then it is probably unstable – tiny changes in the input values, compiler, or CPU may change the result and make the comparison be false."
From http://www.cygnus-software.com/papers/comparingfloats/Comparing%20floating%20point%20numbers.htm
Hope this answers your question.
Also you had a problem with
if(x==ceilf(x))
ceilf() returns a float value and x you have declared as a double.
Refer to problems in floating point comparison as to why that wont work.
change x to float and the program runs fine,
I made a plain try on my laptop and even online compilers.
g++ (4.9.2-10) gave the desired output (3 outputs), along with online compiler at geeksforgeeks.org. However, ideone, codechef did not gave the right output.
All I can infer is that online compilers name their compiler as "C++(gcc)" and give wrong output. While, geeksforgeeks.org, which names the compiler as "C++" runs perfectly, along with g++ (as tested on Linux).
So, we could arrive at a hypothesis that they use gcc to compile C++ code as a method suggested at this link. :)
#include <iostream>
using namespace std;
int main()
{
cout.precision(32);
float val = 268433072;
float add = 13.5;
cout << "result =" << (val + add) << endl;
}
I'm compiling the above program with standard g++ main.cc
and running it with ./a.out
The ouput I receive however, is,
result =268433088
Clearly, this is not the correct answer..Why is this happening?
EDIT: This does not occur when using double in place of float
You can reproduce your "float bug" with an even simpler piece of code
#include <iostream>
using namespace std;
int main()
{
cout.precision(32);
float val = 2684330722;
cout << "result =" << val << endl;
}
The output
result =2684330752
As you can see the output does not match the value val was initialized with.
As it has been stated many times, floating-point types have limited precision. Your code sample simply exceeded that precision, so the result got rounded. There's no "bug" here.
Aside from the reference to (1991, PDF) What Every Computer Scientist Should Know About Floating-Point Arithmetic
The short answer is, that because float has limited storage (like the other primitives too) the engineers had to make a choice: which numbers to store with which precision. For the floating point formats they decided to store numbers of small magnitude precisely (some decimal digits), but numbers of large magnitude very imprecisely, in fact starting with +-16,777,217 the representable numbers are becoming so thin that not even all integers are represented which is the thing you noticed.
Program:
void DibLaplacian8Direct(CDib sourceImg)
{
register int i,j;
int w = sourceImg.GetWidth();
int h = sourceImg.GetHeight();
CDib cpyImage = sourceImg;
BYTE** pSourceImg = sourceImg.GetPtr();
BYTE** pCpyImage = cpyImage.GetPtr();
float G;
for(j =1;j<h-1;j++)
{
for(i =1;i<w-1;i++)
{
G = -1*pCpyImage[j-1][i-1] + -1*pCpyImage[j-1][i] + (-1)*pCpyImage[j-1][i+1]+
(-1)*pCpyImage[j][i-1] + 8*pCpyImage[j][i] + (-1)*pCpyImage[j][i+1]+
-1*pCpyImage[j+1][i-1] + (-1)*pCpyImage[j+1][i] + -1*pCpyImage[j+1][i+1];
pSourceImg[j][i] = (BYTE)G;
}
}
}
warning error:
warning.. Can't coonvert from int to float..
Warning 1 warning C4819: The file contains a character that cannot be represented in the current code page (1257). Save the file in Unicode format to prevent data loss D:\2nd\imagetool\dibfilter.cpp 1 1 ImageTool
I do't understand that why its making me warning of int to float.
and for warning 1,
I am using VS 2010.. i do't know that i am getting warning in StdAfx.h include file .
Amy one can help me with this .
The first warning is due to the fact that a float has only six significant figures whereas an int can have more. If it does, then accuracy is lost.
In general, you cannot convert an integer to floating point without possible losing data. Also, you cannot convert from floating point back to integer without losing the deceimal places, so you get a warning again.
A simple minimalistic code example of the above case:
#include<iostream>
using namespace std;
int main()
{
int a=10;
int b=3;
float c;
c=a/b;
cout << c << endl;
return 0;
}
If you are sure of the data being in the range and there wont be any loss of accuracy you can use typecasting to get rid of the warning.
G = (float) (.....)
Check this for the second warning.
To get rid of the second warning you need to save the file in Unicode format.
Go to file->advanced save options and under that select the new encoding you want to save it as. UTF-8 or UNICODE codepage 1200 are the settings you want.
It is important to understand what the compiler is telling you with warning 20. The issue is that floating point numbers have only 23 bits of precision, while ints have 31. If your numbers is larger than 2^23, you will lose the low bits by storing in a float.
Now your number can never be larger than 2^23, so you are fine. Still, it is important to know what is going on here. There is a reason for that warning, and simply putting in the cast without understanding what is going on may mess you up some day.
In your specific case, I am not at all clear on why you are using a float. You are adding nine integers, none of which can be greater than 2^11. You have plenty of precision in an int to do that. Using a float is just going to slow your program down. (Probably quite a bit.)
Finally, that last cast to BYTE is worrisome. What happens if your value is out of range? Probably not what you want. For example if BYTE is unsigned, and your float ends up -3.0, you will be storing 253 as the result.