This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 4 years ago.
Below you can find a basic C++ exercise with a for loop, the question is: what is the value of i after the loop runs. (Apparently, the value is 5.)
My question, on the 5th run (i=5), the value of a is 100, shouldn't the loop stop since the condition is a<100? Isn't the condition checked after a is multiplied with 10? (so after a is already 100)
If I check the value of a after the loop exit, it will be 1000. I am confused. Why does the loop not stop at 100?
#include <iostream>
using namespace std;
int main(void) {
float a;
int i = 0;
for(a = 0.01; a < 1e2; a *= 1e1)
++i;
return 0;
}
The exercise is designed to show that float (and double etc., floating point numbers in general) do not have the exact decimal value as what you see in the program text.
0.01 (decimal) cannot be exactly represented in the binary floating point format used, therefore multiplying 10 five times will not yield exactly 100.0.
See also: Floating point inaccuracy examples
You can't tell exactly what will happen with this code without knowing the details of the floating point implementation on your platform; the C++ standard leaves this intentionally flexible.
In essence 0.01 could be an approximation for the closest float to that double literal. So the stopping conditional a < 1e2 could be met prematurely or otherwise.
Note that along with 0.01, 1e1 is a literal of type double.
So the conversions to float are complicating things further. Then there is floating point strictness to consider.
Cut a long story short: don't use a floating point as the "index" in a loop.
Related
This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 2 years ago.
Below is the program I've written to find the exponent of 6, but I this its giving wrong output or I may be wrong somewhere, I'm unable to figure out here.
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
ll t;
cin>>t;
cout<<log(t)/log(6)<<"\n";
cout<<floor(log(t)/log(6))<<"\n";
cout<<ceil(log(t)/log(6));
return 0;
}
Input:-
216
Output:-
3
3
4
Since 216 can be written as 6*6*6, so whether there is ceil or floor the output should be 3 in all three cases.
Answering to my own question, this problem can be solved by setting small precision(here up to 2 decimal digits), below is the program for the same.
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin>>t;
cout<<log(t)/log(6)<<"\n";
cout<<floor((floor(log(t)/log(6)*100.0)/100.0))<<"\n";
cout<<ceil((floor(log(t)/log(6)*100.0)/100.0));
return 0;
}
The log function - like most floating point calculations - is imprecise. There is often tiny amount of error in the result. In your case, you did not get the exact 3, but some value slightly greater than 3. When you apply ceil or floor to such imprecise result, you may increase or reduce the amount of the error up to a whole number. In this case you increased the error by ceiling the result from nearly correct integer to exactly following integer).
If you want to find the exponent of an integer with respect to a given radix, then repeated division and checking the remainder is a good starting point. There are faster ways (related to exponentation by squaring) which you could investigate if you want to squeeze out more performance.
The problem is that using the ratio of two log calls and truncating that to an int is bound to give you an inexact answer since the result of a log most likely cannot be represented exactly as a floating point value, and the log function itself may not recover the best floating point value possible (neither the C++ standard nor IEEE754 insist on that).
Finally, on #define ll long long, don't do that. It only serves to obfuscate. And #include<bits/stdc++.h> is not portable C++.
This question already has answers here:
strange output in comparison of float with float literal
(8 answers)
Closed 4 years ago.
#include<iostream.h>
using namespace std;
int main()
{
float x=1.1;
if(x==1.1)
cout<<"yes";
else
cout<<"no";
return 0;
}
I assign value 1.1 to x and checked value of x is 1.1 or not?
You've wandered into an interesting area of almost all programming languages. Floating point values are tricky things, and testing them for equality is very rarely recommended. The basic problem is that floating point values on modern computers are represented as binary decimals with a finite number of digits of precision.
To make this simpler to understand, lets work with base 10 decimals and use a number that can't be accurately represented using them. Take 1/3. If you are representing it as a base 10 decimal you get this:
0.̅3 (there is a bar over the three if it isn't showing up properly). Basically, it goes on forever, there is no finite number of digits that can represent 1/3 as a base ten decimal with perfect accuracy. So, if you only have so many digits, you chop it off and approximate:
0.333333
That's actually 333333/1000000, which is really close to 1/3, but not quite.
C++ has a few different floating point types. And these types usually (it depends on the platform the program is being compiled for) have different numbers of significant digits. By default, a floating point constant is of type double which usually has more digits than a float (and it never has less). Again, using base 10 as an example, since you were storing your value in a float you were doing something like this:
0.333333 == 0.3333333333333333333
which of course is false.
If you wrote your code this way:
#include <iostream>
using namespace std;
int main()
{
float x = 1.1f;
if(x == 1.1f)
cout<<"yes";
else
cout<<"no";
return 0;
}
you would likely get the expected result. Putting an f at the end of a bare floating point value (aka, a floating point literal) tells C++ that it's of type float.
This is all very fascinating of course, and there's a lot to get into. If you would like to learn a lot more about how floating point numbers are really represented, there is a nice Wikipedia page on IEEE 754 floating point representation, which is how most modern processors represent floating point numbers nowadays.
From a practical standpoint, you should rarely (if ever) compare floating point numbers for equality. Usually, a desire to do so indicates some sort of design flaw in your program. And if you really must than use an 'epsilon' comparison. Basically, test to see if your number is 'close enough', though determining what that means in any given situation isn't necessarily a trivial task, which is why it usually represents a design flaw if you need to compare them for equality at all. But, in your case, it could look like this:
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
float x=1.1;
if (fabs(x - 1.1) < 0.000001)
cout<<"yes";
else
cout<<"no";
return 0;
}
The reason the compare fails is that you're comparing a double value to a float variable.
Some compilers will issue a warning when you assign a double value to a float variable.
To get the desired output, you could try this:
double x = 1.1;
if (x == 1.1)
or this:
float x = 1.1f;
if (x == 1.1f)
This question already has answers here:
Division not outputting correct answer c++
(2 answers)
Closed 7 years ago.
I'm currently working on a C++ program where I have a bankAccount class and I need to calculate interest. Problem is, my function is rounding off my numbers to the whole number, even though I'm using a float as my variable type. So if I had code like this:
float BankAccount::CalculateInterest(int Time)
{
float thing;
thing = (967 / 365);
return thing;
}
thing ends up equaling 2.00000000, when it should equal 2.649315068.
Any ideas? I had my interest equation in there before, and the result was always 1.00000000 no matter what, so I put this in as a test and I saw that it's rounding to the "floor".
Thanks for your help!
It's not rounding.
You are dividing two integers and the result will be an integer.
You can remedy this by simply adding ".0" to both numbers, or explicitly defining them as floats.
967 and 365 are integers, so integer division is used and the remainder discarded. Make one a floating point number and floating point division will be done: 967 / 365.0.
Alternatively:
float thing = 967; // integer converted to float during assignment
thing /= 365; // division of float and converted integer
This question already has answers here:
Is floating point math broken?
(31 answers)
How dangerous is it to compare floating point values?
(12 answers)
Closed 7 years ago.
for(float i=1; i<=1.5; i+=0.1)
{
// statements
}
The above C++ for loop runs for 5 times. Shouldn't this run for 6 times?
This is a great example of a floating point precision error. Precise values like multiples of 0.1, 0.2 cannot be precisely represented internally in the computer's memory. You'll want to do a comparison using EPSILON (http://en.cppreference.com/w/cpp/types/numeric_limits/epsilon)
Something like
for (float i = 1; fabs(1.5 - i) < EPSILON; i+=0.1) {
//statements
}
It is because multiples of 0.1 cannot be presented precisely in binary, and the actual value stored is an approximation that may be slightly less than 0.1. So, 5*0.1 might be less than 0.5 or it might be more (depending on how the floating point values are represented).
It is usually a really bad idea to use a floating point variable (and tests involving equality or inequality of floating point values) to control loops at all. Effects can include running more (or less) times that intended, or - in some bad cases - an infinite loop where a finite number of runs was expected.
In your case, you would be better off doing something like
for (int i = 0; i < 5; ++i)
{
float value = 1.0 * i*0.1;
// use value here rather than the i in your original code
}
Alternatively, you can use some test that allows for the imprecision of floating point (e.g. compare i - 1.5 with some value such as machine epsilon). The catch with this is that the actual number of iterations still potentially has some level of unpredictability, particularly in loops that involve a large number of iterations (e.g. iterating from 1.0 to 50000.0 in steps of 0.01) because rounding errors can either accumulate or cancel out at different stages during the loop.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Floating point inaccuracy examples
I have the following line inside a WHILE loop, in C/C++:
while(...)
{
x = x + float(0.1); // x is a float type. Is the cast necessary?
}
x starts as 0. The thing is, after my first loop, x = 0.1. That's cool. After my second loop, x = 0.2. That's sweet. But, after my third loop, x = 0.3000001. That's not OK. I want it to have 0.3 as value, not 0.3000001. Can it be done? Am I looping wrongly?
Floating point does not work that way there are infinitely many real numbers between any two real numbers and only a finite amount of bits this means that in almost all cases the floating point representation is approximate. Read this link for more info.
It's not the loop, it's just how floats are represented in memory. You don't expect all real numbers to be directly representible in a limited number of bytes, right?
A 0.3 can't be exactly represented by a float. Try a double (not saying it will work, it probably won't, but the offset will be lower).
This is a common misconception with floating point numbers. 0.3 may not be exactly representable with 32bit or 64bit binary floating point. Lots of numbers are not exactly representable. Your loop is working fine ignoring the unnecessary syntax.
while (...)
{
x += 0.1f; /* this will do just fine in C++ and C */
}
If this doesn't make sense consider the fact that there are an infinite number of floating point numbers...with only a finite number of bits to describe them.
Either way, if you need exact results you need to use a decimal type of the proper precision. Good news though, unless you're doing calculations on money you likely do not need exact results (even if you think you do).
Code such as this:
for (int i = 0;… ; ++i)
{
float x = i / 10.f;
…
}
will result in the value of x in each iteration being the float value that is closest to i/10. It will usually not be exact, since the exact value of i/10 is usually not representable in float.
For double, change the definition to:
double x = i / 10.;
This will result in a finer x, so it will usually be even closer to i/10. However, it will still usually not be exactly i/10.
If you need exactly i/10, you should explain your requirements further.
NO the cast is not necessary in this case
float x;
x = x + float(0.1);
You can simply write
x+= 0.1