找到Factorial Trailing Zero时的结果不一致

时间:2017-03-13 03:20:51

标签: java algorithm

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

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

1 个答案:

答案 0 :(得分:4)

这是由于base的值为integer overflow

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

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

正如您在此处所见,base1220703125时增加到n =。然后运行语句base *= 5使其6103515625超出最大32位无符号整数(2^32)正好6103515625 - 2^32 = 1808548329,这就是你所看到的中间错误值b以上(OOPS)。

另一方面,递归解仅使用连续减少的n的值。因此没有溢出。

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

另一个解决方案是将循环修改为仅使用 int base = 5; while (n > 0) { result += n/base; n = n/base; } ,类似于递归解决方案:

class Bunch(dict):
    def __init__(self, *args, **kwargs):
        super(Bunch, self).__init__(*args, **kwargs)
        self.__dict__ = self


    def __getattribute__(self, item):
        try:
            return object.__getattribute__(self, item)
        except:
            return None

my_dict = {'StockSymbol': 'AMD', 'LastTradeTime': '4:00PM EST', 'ChangePercent': '+0.58', 'ID': '327',
           'LastTradeDateTimeLong': 'Mar 10, 4:00PM EST', 'Index': 'NASDAQ', 'LastTradeWithCurrency': '13.91',
           'LastTradeDateTime': '2017-03-10T16:00:02Z', 'LastTradePrice': '13.91', 'LastTradeSize': '0',
           'PreviousClosePrice': '13.33'}

obj = Bunch(**my_dict)
print obj.StockSymbol
print obj.LastTradeTime
print obj.key_not_exist

请注意,在涉及阶乘的问题中,溢出是给定的,您可能需要考虑更高精度的算术,例如BigInteger