Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursive Function and Non-recursive Function Returning Different Results

I'm creating two functions that are supposed to emulate and return the result of f(i) = 1/1 + 1/2 + 1/3 ... 1/i. One function is recursive, and I'm testing that the recursive function functions correctly by implementing a non-recursive version of it. However, I've found that both functions are returning similar answers that are not exactly the same. Can somebody please explain why the functions are returning different values?

When I run the functions in the main method of the class to which they belong, I get the following output:
Recursive for 1000: 7.4854784
Non-Recursive for 1000: 7.4854717
Recursive for 1: 1.0
Non-Recursive for 1: 1.0
Recursive for 483: 6.758268
Non-Recursive for 483: 6.758267

Here's my code:

static float RecursiveFunction(int num){
    //The num parameter represents the denominator that will be used
    //The recursive function is continually called at lower increments of num

    //If num is one, return 1 and do not call RecursiveFunction again
    if (num == 1) {
        return 1;
    }
    //Otherwise, return 1/num (in floating point decimal) and call RecursiveFunction with a parameter of num - 1
    else {
        return 1/(float)num + RecursiveFunction(num - 1);
    }
}

//A Non-recursive version of RecursiveFunction that will be used to test RecursiveFunction
static float NonRecursiveFunction(int num) {
    //The total variable adds up the fractions
    float total = 0;
    //While num is greater than zero, add 1/num to total and then subtract 1 from num
    while (num > 0) {
        total += 1/(float)num;
        num -= 1;
    }
    return total;
}
like image 760
DFrancisFan Avatar asked Mar 14 '26 07:03

DFrancisFan


1 Answers

It is due to rounding errors from using the float datatype which is a single-precision 32-bit IEEE 754 floating point. When the number requires a greater precision than the datatype can cope with it will be rounded - this will happen when you are adding multiple floats together.

If you convert your float datatypes to BigDecimal then you will get the same answer from both methods:

import java.math.BigDecimal;
import java.math.RoundingMode;

public class RoundingErrors {
    private static final BigDecimal ONE = new BigDecimal( 1 );

    static BigDecimal RecursiveFunction(int num){
        //The num parameter represents the denominator that will be used
        //The recursive function is continually called at lower increments of num

        //If num is one, return 1 and do not call RecursiveFunction again
        if (num == 1) {
            return ONE;
        }
        //Otherwise, return 1/num (in floating point decimal) and call RecursiveFunction with a parameter of num - 1
        else {
            return ONE.divide( new BigDecimal( num ), 100, RoundingMode.CEILING ).add( RecursiveFunction(num - 1) );
        }
    }

    //A Non-recursive version of RecursiveFunction that will be used to test RecursiveFunction
    static BigDecimal NonRecursiveFunction(int num) {
        //The total variable adds up the fractions
        BigDecimal total = new BigDecimal( 0 );
        //While num is greater than zero, add 1/num to total and then subtract 1 from num
        while (num > 0) {
            total = total.add( ONE.divide( new BigDecimal( num ), 100, RoundingMode.CEILING ) );
            num -= 1;
        }
        return total;
    }
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println( RecursiveFunction( 1000 ));
        System.out.println( NonRecursiveFunction( 1000 ));
    }
}

Output

7.4854708605503449126565182043339001765216791697088036657736267499576993491652024409599344374118451321
7.4854708605503449126565182043339001765216791697088036657736267499576993491652024409599344374118451321
like image 183
MT0 Avatar answered Mar 16 '26 21:03

MT0



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!