编程语言
首页 > 编程语言> > java-递归函数和非递归函数返回不同的结果

java-递归函数和非递归函数返回不同的结果

作者:互联网

我正在创建两个应该模拟并返回f(i)= 1/1 1/2 1/3 … 1 / i结果的函数.一个函数是递归的,我正在通过实现它的非递归版本来测试递归函数是否正常运行.但是,我发现这两个函数都返回的答案并不完全相同.有人可以解释为什么这些函数返回不同的值吗?

当我在它们所属的类的main方法中运行这些函数时,得到以下输出:
1000的递归:7.4854784
1000的非递归:7.4854717
递归为1:1.0
1:1.0的非递归
483的递归:6.758268
483的非递归:6.758267

这是我的代码:

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;
}

解决方法:

这是由于使用single-precision 32-bit IEEE 754 floating point的float数据类型导致的舍入错误.当数字要求的精度超出数据类型可以应付的精度时,将对其进行舍入-当您将多个float一起添加时会发生这种情况.

如果将float数据类型转换为BigDecimal,则两种方法都将得到相同的答案:

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 ));
    }
}

输出量

7.4854708605503449126565182043339001765216791697088036657736267499576993491652024409599344374118451321
7.4854708605503449126565182043339001765216791697088036657736267499576993491652024409599344374118451321

标签:while-loop,java,recursion
来源: https://codeday.me/bug/20191122/2057134.html