Floor vs int cast difference [duplicate] - c++

This question already has answers here:
Why does floating-point arithmetic not give exact results when adding decimal fractions?
(31 answers)
Closed 6 years ago.
I have a weird problem. Here's part of my code:
int temp=1100;
int foo=floor(0.03*temp);
int foo1=0.03*temp;
if(foo-foo1){
cout<<foo<<endl;
cout<<foo1<<endl;
}
If 3% of temp = integer then foo differs from foo1 by 1.
For example: 1100*0.03=33. foo=33 foo1=32.
In addition if i write it like that :
int foo=floor(0.03*1100);
int foo1=0.03*1100;
There is no such problem.
Why?

Floating point numbers have trouble rendering decimal places. It is more of an approximation.
2**-6 + 2**-7 + 2**-8 + 2**-9 + 2**-11 + 2**-13 + 2**-14 + 2**-15 + 2**-20 + 2**-22 + 2**-26
= 0.0299999863
Using binary, I drove the accuracy to 26 binary. I got close to 0.03 but not quite. In my example I chose to be under 0.03 but I could have gone a little above (i.e. 0.03000001. I don't think it is possible to represent 0.03 perfectly in floating point notation.
Multiplying 0.03 by any number produces yet another approximation. Casting to type int will cut out everything after the decimal place. I assume the implementation of floor is more elegant. Your compiler probably choose a floating point value of 32.99999 so and int would make 32.

Related

c++11 double precision [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 9 months ago.
Doing the following calculation:
double result = 58/10;
Will result: 5.7999999999999998
I know c++ will round it on further calculations or printing, but I need to compare output with where rounding doesn't occur so I can't have rounding happen because that may just lead to differences in other places in the output.
Is there any way to improve the precision of such calculations and having 58/10 result 5.8?
5.8 cannot be exactly represented in floating point. If you are working with 2 digits precision after the decimal point, for example if you need to store monetary values, store it as "580" (e.g., 580 cents) and do your own formatting when printing.
printf("%d.%02d", n / 100, n % 100);
Alternatively store the decimal as a fraction:
struct Fraction {
int numerator;
int denominator;
};
int main() {
Fraction f(29, 5);
}

problem in using 'double' data type in for loops with fractional incrementation [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 3 years ago.
I had a program which requires one to search values from -100.00 to +100.00 with incrementation of 0.01 inside a for loop. But the if conditions arent working properly even if code is correct...
As an example I tried printing a small section i.e if(i==1.5){cout<<"yes...";}
it was not working even though the code was attaining the value i=1.5, i verified that by printing each of the values too.
#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{
double i;
for(i=-1.00; i<1.00; i=i+0.01)
{
if(i>-0.04 && i<0.04)
{
cout<<i;
if(i==0.01)
cout<<"->yes ";
else
cout<<"->no ";
}
}
return 0;
}
Output:
-0.04->no -0.03->no -0.02->no -0.02->no -0.01->no 7.5287e-016->no 0.01->no 0.02->no 0.03->no
Process returned 0 (0x0) execution time : 1.391
(notice that 0.01 is being attained but still it prints 'no')
(also notice that 0.04 is being printed even if it wasn't instructed to do so)
use this if(abs(i - 0.01) < 0.00000000001) instead.
double - double precision floating point type. Usually IEEE-754 64 bit
floating point type
The crux of the problem is that numbers are represented in this format as a whole number times a power of two; rational numbers (such as 0.01, which is 1/100) whose denominator is not a power of two cannot be exactly represented.
In simple word, if the number can't be represented by a sum of 1/(2^n) you don't have the exact number you want to use. So to compare two double numbers calculate the absolute difference between them and use a tolerance value e.g. 0.00000000001 .
Doubles are stored in binary format. To cut things short fractional part is written as binary. Now let's imagine it's size is 1 bit. So you've two possible values (for fraction only): .0 and .5. With two bits you have: .0 .25 .5 .75. With three bits: .125 .25 .375 .5 .625 .75 .875. And so on. But you'll never get 0.1. So what computer does? It cheats. It lies to you, that 0.1 you see is 0.1. While it more looks like 0.1000000000000000002 or something like this. Why it looks like 0.1? Because formatting of floating point values has long standing tradition of rounding numbers, so 0.10000000000001 becomes 0.1. As a result 0.1 * 10 won't equal 1.0.
Correct solution is to avoid floating point numbers, unless you don't care for precision. If your program breaks, once your floating point value "changes" by miniscule amount, then you need to find another way. In your case using non-fractional values will be enough:
for(auto ii=-100; ii<100; ++ii)
{
if(ii>-4 && ii<4)
{
cout << (ii / 100.0);
if(ii==1)
cout<<"->yes ";
else
cout<<"->no ";
}
}

Why float taking 0.699999 instead of 0.7 [duplicate]

This question already has answers here:
Floating point comparison [duplicate]
(5 answers)
Closed 9 years ago.
Here x is taking 0.699999 instead of 0.7 but y is taking 0.5 as assigned. Can you tell me what is the exact reason for this behavior.
#include<iostream>
using namespace std;
int main()
{
float x = 0.7;
float y = 0.5;
if (x < 0.7)
{
if (y < 0.5)
cout<<"2 is right"<<endl;
else
cout<<"1 is right"<<endl;
}
else
cout<<"0 is right"<<endl;
cin.get();
return 0;
}
There are lots of things on the internet about IEEE floating point.
0.5 = 1/2
so can be written exactly as a sum of powers of two
0.7 = 7/10 = 1/2 + 1/5 = 1/2 + 1/8 + a bit more... etc
The bit more can never be exactly a power of two, so you get the closest it can manage.
It is to do with how floating points are represented in memory. They have a limited number of bits (usually 32 for a float). This means there are a limited number of values that can be represented which means that many numbers from the infinite set of real numbers cannot be represented.
This website explains further
If you want to understand exactly why, then have a look at floating point representation of your machine (most probably it's IEEE 754, https://en.wikipedia.org/wiki/IEEE_floating_point ).
If you want to write robust and portable code, never compare floating-point values for equality. You should always compare them with some precision (e.g. instead of x==y you should write fabs(x-y) < eps where eps is say 1e-6).
floating point representation is approximate only as you cannot have precise representation of real, non-rational numbers on a computer.
`
when operating on floats, errros will in general accumulate.
however, there are some reals which can be represented exactly on a digital computer using it's native datatype for this purpose (*), 0.5 being one of them.
(*) meaning the format the floating point processing unit of the cpu operates on (standardized in ieee754). specialized libraries can represent integer and rational numbers exactly beyond the limits of the processor's internal formats. rounding errors may still occur when converting into a human-readable decimal expansion and the alternative also does not extend to irrational numbers (e.g. sqrt(3)). and, of course, these libraries comes at the cost of less speed.

Can someone explain to me why float x = 0.1 * 7 does not result in x == 0.7 to be true? [duplicate]

This question already has answers here:
strange output in comparison of float with float literal
(8 answers)
Closed 9 years ago.
EDIT: There are a lot of disgruntled members here because this question had a duplicate on the site. In my defense, I tried searching for the answer FIRST, and maybe I was using poor searching keywords, but I could not find a direct, clear answer to this specific code example. Little did I know there was one out there from **2009** that would then be linked to from here.
Here's a coded example:
#include <iostream>
using namespace std;
int main() {
float x = 0.1 * 7;
if (x == 0.7)
cout << "TRUE. \n";
else
cout << "FALSE. \n";
return 0;
}
This results in FALSE. However, when I output x, it does indeed output as 0.7. Explanation?
Please read What Every Computer Scientist Should Know About Floating-Point Arithmetic.
First of all, 0.1 is a literal of type double. The closest representable value to 0.1 in IEEE 754 double-precision is:
0.1000000000000000055511151231257827021181583404541015625
If you multiply that by 7, the closest representable value in IEE 754 single-precision (since you're storing it in a float) is:
0.699999988079071044921875
Which, as you can see, is almost 0.7, but not quite. This then gets converted to a double for the comparison, and you end up comparing the following two values:
0.699999988079071044921875 == 0.6999999999999999555910790149937383830547332763671875
Which of course evaluates to false.
This is because numbers are stored in binary. In binary, you cannot exactly represent the fraction .1 or .7 with finitely many places, because these have repeating expansions in binary. something like 1/2 can be represented exactly with the representation .1, but .1 in decimal for instance is .0001100110011.... So, when you cut off this number, you're bound to have roundoff error.
Doubles and floats should never be compared by the == operator. Numbers are stored in memory inaccurately because in binary they don't have to have finite representation (for example 0.1).
You will see it here:
#include <iostream>
using namespace std;
int main() {
float x = 0.1 * 7;
cout << x-0.7;
return 0;
}
The difference is NOT zero, but something very very close to zero.
Like every datatype a float is represented as binary number. For the exact representation see here: http://en.wikipedia.org/wiki/IEEE_floating_point
When converting a decimal number to a floating point number by hand, you first have to convert it to a fixed point number.
Converting 0.7 to base 2 (binary):
0.7 = 0.101100110011...
As you see it has infinite digits after the comma, so when representing it as a float datatype, some digits will get cut off. This results in the number not being EXACTLY 0.7 when converting it back to decimal.
In your example the multiplication results in a different number than the literal "0.7".
To fix this: Use a epsilon when comparing equality of floats:
if (x < 0.71f && x > 0.69f)

Sum Float number c++ [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Floating point error in representation?
I have problem with this code
int cent;
int dollar ;
float cnt2dlr;
//convert cnt to doloar ;
cnt2dlr=(cnt)/(100);
The problem is when cnt = 175, cnt2dlr = 0.17,444444 and not 0.17,5
Any help?
Floating point numbers are often inexact. There is nothing you can do about it.
Your code is a good illustration of why you should not use floating point numbers for calculations involving money. Just because currency values have a decimal point does not make money a floating point quantity. Floating points should be used for quantities which vary infinitesimally, like temperature or speed, not for quantities which vary in chunks, like money.
Floating point numbers are not exact representations. They are approximations, so you cannot guarantee much precision. Read What Every Computer Scientist Should Know About Floating-Point Arithmetic
To increase the precision of the numbers, consider using a 64-bit double instead of a 32-bit float.
I am a bit puzzled. If you mean (cent) instead of (cnt), then
cnt2dlr=(cent)/(1000);
(note the e in cent) is an int / int division, and 175 / 1000 should return int 0.
Do you get the same result if you do, eg
cnt2dlr=(cent)/(1000.0);
note the decimal point.