发现阶乘尾随零时结果不一致 [英] inconsistent results when finding Factorial Trailing Zero

查看:113
本文介绍了发现阶乘尾随零时结果不一致的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我编写的两个版本的代码,用于返回n!中的尾随零。第一个版本返回 452137080 作为输入 1808548329 ,第二个版本返回 452137076 作为输入 1808548329 。想知道为什么会有区别吗?第二版本的输出是正确的。

Here are two versions of code I write to return the number of trailing zeroes in n!. The first version returns 452137080 for input 1808548329, the 2nd version returns 452137076 for input 1808548329. Wondering why there is a difference? The output from 2nd version is correct.

Java源代码

public class TrailingZero {
    public static int trailingZeroes(int n) {
        int result = 0;
        int base = 5;
        while (n/base > 0) {
            result += n/base;
            base *= 5;
        }

        return result;
    }

    public static int trailingZeroesV2(int n) {
        return n == 0 ? 0 : n / 5 + trailingZeroesV2(n / 5);
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println(trailingZeroes(1808548329));
        System.out.println(trailingZeroesV2(1808548329));
    }
}


推荐答案

此是由于整数溢出的值 base

稍微更改代码以打印 n / base base

Changing your code slightly to print n / base and base:

public class TrailingZero {
    public static int trailingZeroes(int n) {
        int result = 0;
        int base = 5;
        while (n/base > 0) {
            System.out.println("n = " + n/base  + " base = " + base);
            result += n/base;
            base *= 5;
        }

        return result;
    }

    public static int trailingZeroesV2(int n) {
        return n == 0 ? 0 : n / 5 + trailingZeroesV2(n / 5);
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println(trailingZeroes(1808548329));
        System.out.println(trailingZeroesV2(1808548329));
    }
}

输出:

n = 361709665 base = 5
n = 72341933 base = 25
n = 14468386 base = 125
n = 2893677 base = 625
n = 578735 base = 3125
n = 115747 base = 15625
n = 23149 base = 78125
n = 4629 base = 390625
n = 925 base = 1953125
n = 185 base = 9765625
n = 37 base = 48828125
n = 7 base = 244140625
n = 1 base = 1220703125
n = 1 base = 1808548329   <== OOPS 6103515625 overflows 32-bit integer
n = 3 base = 452807053
452137080

在这里您可以看到,<$当 n = 1时,c $ c> base 增加到 1220703125 。然后语句 base * = 5 运行,这使得它 6103515625 超出了最大32位无符号整数( 2 ^ 32 )恰好是 6103515625-2 ^ 32 = 1808548329 ,这就是中间错误值 b 以上( OOPS )。

As you can see here, base increases to 1220703125, when n =1. Then the statement base *= 5 runs which makes it 6103515625 which is overshoots the maximum 32-bit unsigned int (2^32) by exactly 6103515625 - 2^32 = 1808548329, and that is what you see as the intermediate wrong value of b above (OOPS).

在另一方面,递归解决方案仅使用 n 的值,该值不断减小。因此,没有溢出。

On the other hand, the recursive solution only uses the value of n which continuously decreases. Hence there is no overflow.

简单的解决方案是声明 base 长,即 long base = 5 。这将返回正确的值 452137076

The simple solution is to declare base as long, i.e., long base = 5. That will return the right value of 452137076.

另一种解决方案是将循环修改为仅使用 n ,类似于递归解决方案:

Another solution will be to modify the loop to only use n, similar to the recursive solution:

    int base = 5;
    while (n > 0) {
        result += n/base;
        n = n/base;
    }

请注意,在涉及阶乘的问题中,溢出是给定的,您可能想要考虑使用诸如 BigInteger 之类的高精度算术。

Note that in problems involving factorials, overflow is a given and you may want to consider higher precision arithmetic such as BigInteger.

这篇关于发现阶乘尾随零时结果不一致的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆