Problems while dividing by 100 [duplicate] - c++

This question already has answers here:
Division in C++ not working as expected
(6 answers)
Closed 8 years ago.
Helo, I'm new to programming and run into an issue, I have an integer, for example 158, and I divide it by 100 that i get is 1, but I want 1.58 instead
It is probably known issue, but sorry, I'm noob, for now :)

Just cast this to float number
int i = 158;
float f = (float)i / 100; //less precision
double d = (double)i / 100; //more precision
//other way
int i = 158;
float f = i / 100.0; //less precision
double d = i / 100.0; //more precision
What you are doing is dividing integer from integer, in this case result always integer, to get floating point number at least one of two operand has to be floating point number.

You need to divide by 100.0 rather than 100

Dividing by an integer in C++ is always going to give you an integer, so it will never be completely accurate. That being said, it was mentioned above that you can divide by a double or long to get the accurate decimal number that you desire.

Related

Why do I have to add a decimal to get this math correct in C++ [duplicate]

This question already has answers here:
What is the behavior of integer division?
(6 answers)
Closed 4 years ago.
I was calculating the volume of a sphere and after tons of research I found that I cannot use:
float sphereRadius = 2.33;
float volSphere = 0;
volSphere = (4/3) * (M_PI) * std::pow(sphereRadius, 3);
But must add the 3.0 instead to get the right answer.
volSphere = (4/3.0) * (M_PI) * std::pow(sphereRadius, 3);
Why must a decimal be added to get the correct calculation?
(4/3) is one integer divided by another integer, which results in another integer. An integer can't be 1.33 or anything like that, so it gets truncated to 1. With the decimal, you're telling it to be a double instead, and dividing an integer by a double results in a double, which supports fractions.

In which segment a given number lies in? [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 6 years ago.
Suppose to have n (integer) contiguous segments of length l (floating point). That is:
Segment 0 = [0, l)
Segment 1 = [l, 2*l)
Segment 2 = [2*l, 3*l)
...
Segment (n-1) = [(n-1)*l, n*l)
Given a number x (floating point) I want to determine the id of the segment it lies inside.
My first idea is the following:
int segmentId = (int) floor(x/l);
Anyway, this sometimes does not work. For example, consider
double l = 1.1;
double x = 5.5;
int segmentId = (int) floor(x/l); //returns 5
double l = 1.1;
double x = 6.6;
int segmentId = (int) floor(x/l); //returns 5!!!
Of course, due to finite arithmetic, this does not work well.
Maybe some extra checks are required in order to have a robust implementation, but I really don't know how to proceed further.
The question is: how would you solve the problem "In which segment a given number lies in?"
Your problem is that neither 1.1, nor 6.6 are representable exactly in binary floating point. So when you type
double l = 1.1;
double x = 6.6;
you get 2 numbers stored in l and in x, which are slightly different than 1.1 and 6.6. After that, int segmentId = (int) floor(x/l); determines the correct segment for those slightly different numbers, but not for the original numbers.
You can solve this problem by using a decimal floating point data type instead of binary. You can check C++ decimal data types and Exact decimal datatype for C++? for the libraries, or implement the decimal data type yourself.
But still the problem will remain for numbers, which are not representable in finite decimal floating point, such as 1/3 (circulating fraction), sqrt(2) (irrational), pi (transcendental), etc.
Just in case u don't specifically want an O(1) answer you can go for the O(logn) answer by just doing a binary search on the segments.
What precision does your solution require? There can always be a problem with marginal values for given segment, cause they are most likely unrepresentable.
I think adding a very small epsilon in this case could help. However it may fail in other case.
Check the segments again after the division.
bool inSegment(double x, double l, double segment)
{
return (x >= l*(segment-1)) && (x < l*segment);
}
int segmentId;
double segment = floor(x/l);
if (inSegment(x, l, segment-1))
segmentId = segment - 1;
else if (inSegment(x, l, segment))
segmentId = segment;
else if (inSegment(x, l, segment+1))
segmentId = segment + 1;
else
printf("Something wrong happened\n");
Or use an epsilon and round the value up if the value is close enough to an integer above.
how would you solve the problem "In which segment a given number lie in?"
You should divide the number by the segment length, then truncate the fractional part away. Like this:
int segmentId = (int) floor(x/l);
It seems that you have already figured this out.
Of course, due to finite arithmetic, this does not work well.
If the result of 6.6 / 1.1 happens to be5.9999999999999991118215802998747676610946655273438, then 5 is in fact the correct segment for the result.
If you would like 6.6 / 1.1 to be exactly 6, then your problem is with finite precision division, which doesn't do what you want and with finite precision representation of floating point numbers that has no exact representation for all numbers. The segmentation itself worked perfectly.
I really don't know how to proceed further
Either don't use finite precision floating point (use fixed or arbitrary precision), or don't require the results of calculations to be exact.

Print 2 decimals from float value [duplicate]

This question already has answers here:
C++ program converts fahrenheit to celsius
(8 answers)
Closed 7 years ago.
First of all, I want to say sorry because I think the doubt is so trivial... but I'm new programming in C++.
I have the following code:
int a = 234;
int b = 16;
float c = b/a;
I want to print the result from float c with 2 decimals (the result should be 0.06) but I don't get the expected result.
Can anyone can help me? I tried using CvRound() and setPrecision() but nothing works like I expect or, in my case, I don't know how to do them working.
The problem is actually blindingly simple. And has NOTHING whatsoever do do with settings such as precision.
a and b are of type int, so b/a is also computed to be of type int. Which involves rounding toward zero. For your values, the result will be zero. That value is then converted to be float. An int with value zero, when converted to float, gives a result of 0.0. No matter what precision you use to output that, it will still output a zero value.
To change that behaviour convert one of the values to float BEFORE doing the division.
float c = b/(float)a;
or
float c = (float)b/a;
The compiler, when it sees a float and and an int both participating in a division, converts the int to float first, then does a division of floats.
int a = 234;
int b = 16;
float c = b/(float)a;
float rounded_down = floorf(c * 100) / 100; /* floor value upto two decimal places */
float nearest = roundf(c * 100) / 100; /* round value upto two decimal places */
float rounded_up = ceilf(c * 100) / 100; /* ceiling value upto two decimal places */
If you just want to print the result, you can use a printf() formatting string to round:
printf("c = %.2f\n", number, pointer);
Otherwise, if you need c to calculate another value, you shouldn't round the original value, only the one to print.
try this:
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
int a = 234;
int b = 16;
float c = float(b)/a;
cout<<fixed<<setprecision(2)<<c;
return 0;
}
Previously when c = b/a since a and b are integers so by integer division we were getting answer as 0 as per your program.
But if we typecast one of the variable(a or b) to float we will obtain decimal answer.
Number of digits after decimal may or may not be 2. To ensure this we can use fixed and setprecision. fixed will ensure that number of digits after decimal will be fixed. setprecision will set how many digits to be there after decimal.

double to scientific notation conversion - precision error

I'm writing a piece of code to convert double values to scientific notations upto a precision of 15 in C++. I know I can use standard libraries like sprintf with %e option to do this. But I would need to come out with my own solution.
I'm trying something like this.
double norm = 68600000;
if (norm)
{
while (norm >= 10.0)
{
norm /= 10.0;
exp++;
}
while (norm < 1.0)
{
norm *= 10.0;
exp--;
}
}
The result I get is
norm = 6.8599999999999994316;
exp = 7
The reason for loosing this precision I clarified from this question
Now I try to round the value to the precision of 15, which would result in
6.859 999 999 999 999
(its evident that since the 16th decimal point is less than 5 we get this result)
Expected answer: norm = 6.860 000 000 000 000, exp = 7
My question is, is there any better way for double to scientific notation conversion to the precision of 15(without using the standard libs), so that I would get exactly 6.86 when I round. If you have noticed the problem here is not with the rounding mechanism, but with the double to scientific notation conversion due to the precision loss related to machine epsilon
You could declare norm as a long double for some more precision. long double wiki Although there are some compiler specific issues to be aware of. Some compilers make long double synonymous with double.
Another way to go about solving this precision problem is to work with numbers in the form of strings and implement custom arithmetic operations for strings that would not be subject to machine epsilon.
For example:
int getEXP(string norm){ return norm.length() - 1; };
string norm = "68600000";
int exp = getEXP(norm); // returns 7
The next step would be to implement functions to insert a decimal character into the appropriate place in the norm string, and add whatever level of precision you'd like. No machine epsilon to worry about.

Losing Double Precision when multiplying by multiple of 10 [duplicate]

This question already has answers here:
Precision loss with double C++
(4 answers)
Closed 9 years ago.
So I have the following code
int main(){
double d;
cin>>d;
while(d!=0.00)
{
cout<<d<<endl;
double m = 100*d;
int n = m;
cout<<n<<endl;
cin>>d;
}
return 0;}
When I enter the input 20.40 for d the value of n comes out to be 2039 instead of 2040.
I tried replacing int n = m with int n = (int) m but the result was the same.
Is there any way to fix this. Thanks in advance.
Your code truncates m but you need rounding. Include cmath and use int n = round(m).
Decimal values can, in general, not be represented exactly using binary floating points like double. Thus, the value 20.40 is represented as an approximation which can be used to restore the original value (20.4; the precision cannot be retained), e.g., when formatting the value. Doing computations with these approximated values will typically amplify the error.
As already mentioned in one of the comments, the relevant reference is the paper "What Every Computer Scientist Should Know About Floating-Point Arithmetic". One potential way out of your trouble is to use decimal floating points which are, however, not yet part of the C++ standard.
Single and double presicion floating point numbers are not stored the same way as integers, so whole numbers (e.g. 5, 10) may actually look like long decimals (e.g. 4.9999001, 10.000000001). When you cast to an int, all it does is truncate the whole number. So, if the number is currently represented as 4.999999999, casting it to an int will give you 4. std::round will provide you with a better result most of the time (if the number is 4.6 and you just want the whole number portion, round will not work well). The bigger question is then: what are you hoping to accomplish by casting a double to an int?
In general, when dealing with floating point numbers, you will want to use some epsilon value that is your minimum significant digits. So if you wanted to compare 4.9999999 to 5, you would do (pseudo-code): if abs(5 - 4.9999999) < epsilon, return 5.
Example
int main()
{
double d;
std::cin >> d;
while (std::fabs(d - 0.0) > DBL_EPSILON)
{
std::cout << d << std::endl;
double m = 100 * d;
int n = static_cast<int>(m);
if (std::fabs(static_cast<double>(n) - m) > DBL_EPSILON)
{
n++;
}
std::cout << n << std::endl;
std::cin >> d;
}
return 0;
}
Casting double to int truncates value so 20.40 is probably 20.399999 * 100 is 2039.99 because double is not base 10. You can use round() function that will not truncate but will get you nearest int.
int n = round(m);
Floating point numbers can't exactly represent all decimal numbers, sometimes an approximation is used. In your example the closest possible exact number is 20.39999999999999857891452847979962825775146484375. See IEEE-754 Analysis for a quick way to see exact values.
You can use rounding, but presumably you're really looking for the first two digits truncated. Just add a really small value, e.g. 0.0000000001 before or after you multiply.