I need to add a series of fractions. I looked through other for
loops on adding fractions, but did not come across the problem I am having. The fractions denominator increases by 1.0 each time until it adds up 1.0/1.0 + 1.0/2.0 + .... + 1.0/ 150,000,000.0. My code has worked for me by adding the fractions until I go a little over 10,000,000 in my for loop. Once I go over say 15,000,000 it just doesn't print anything and the program continues to run. What error did I make? Why won't it print the answer when it's above a certain number?
Here is the code:
float sum = 0;
float numerator = 1;
float denominator = 1;
for(float i = 1; i <= 10000000; i++)
{
sum = ((float)numerator/denominator) + sum;
denominator++;
}
System.out.println("The sum is " + sum);
Adding 1
to a sufficiently large float
won't have any effect any more. The problem is the limited precision of a float
-- 23 bits. Once you get to about 16 million (about 224), the difference between consecutive float values is greater than 1. You can see this by printing out the result of Math.ulp
(unit in last place) value.
if (denominator % 1000 == 0)
System.out.println("Denominator is " + denominator + ", ulp is " + Math.ulp(denominator));
At the point where the output stops, the ulp is 1.0.
...
Denominator is 1.6775E7, ulp is 1.0
Denominator is 1.6776E7, ulp is 1.0
Denominator is 1.6777E7, ulp is 1.0
At 224, the ulp jumps to 2.0, and adding 1.0 follows IEEE's round towards even rule, and the sum is unchanged.
Change the datatypes to double
for a much larger precision (53 bits). Just beware that this change would only prolong the problem until you reach 253. That would also make your program run much longer. And if you really want to go beyond that amount, use BigDecimal
s.
Instead of writing more comments here are my thoughts:
Floats have limited precision. It means that if you add very, very small numbers, the outcome might not be what you'd expect. It also works the other way - adding 1 to a very large number won't change it's value.
In your program to avoid this problem you should increment integer values and cast them to float before summation. Like this:
public class Sum {
public static void main(String[] args) {
// TODO Auto-generated method stub
float sum = 0;
float numerator = 1;
int denominator = 1; //changed to int
for(int i = 1; i <= 10000000; i++)
{
sum = (numerator/(float)denominator) + sum; //this casts denominator to float
denominator++; //this will now increment integer
}
System.out.println("The sum is " + sum);
}
}
Further reading: Floating point on wikipedia
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With