1

考虑以下代码片段 -

def factorial(number) {
    if(number == 1)
        return number;
    else 
        return number * factorial(number - 1);
}

println factorial(50)
println factorial(50).getClass()

println()

println 45**20
println ((45**20).getClass())

输出是 -

0
class java.lang.Integer

1159445329576199417209625244140625
class java.math.BigInteger

问题 -

  1. 为什么 groovy在第一种情况下不会自动将结果提升number * factorial(number-1)为 a ?BigInt
  2. 为什么输出为0?为什么不是整数溢出后我们应该得到的随机数?
4

2 回答 2

1

老问题,但我会尝试回答问题的两个部分:

关于算术运算的 Groovy 文档指出

涉及子类的二元运算java.lang.Number根据以下矩阵自动转换其参数(除法除外,下文将讨论)

我不会粘贴矩阵,但它指定不强制转换为BigIntegerBigDecimal除非运算符之一属于这些类型之一。

在分割的情况下:

如果任一操作数是 Float 或 Double,则除法运算符“/”和“/=”产生 Double 结果,否则产生 BigDecimal 结果

我认为该表没有考虑幂运算符 ( **),因为它在 Java 中不存在,并且如 @tim_yates 评论中所述,默认情况下power使用实现BigInteger

中的代码DefaultGroovyMethods.java清楚地表明 's 的幂int是使用 's 计算BigInteger的,如果结果很小,则再次转换为 int (这就是为什么(2**4).classis java.lang.Integer):

public static Number power(Integer self, Integer exponent) {
    if (exponent >= 0) {
        BigInteger answer = BigInteger.valueOf(self).pow(exponent);
        if (answer.compareTo(BI_INT_MIN) >= 0 && answer.compareTo(BI_INT_MAX) <= 0) {
            return answer.intValue();
        } else {
            return answer;
        }
    } else {
        return power(self, (double) exponent);
    }
}

要确认其他操作的行为,您可以转到org.codehaus.groovy.runtime.typehandling 包IntegerMathLongMath的其他类

于 2013-10-03T06:57:41.320 回答
0

使用 Groovy,Integer.multiply( Integer )总是返回一个整数。

阶乘方法在第 16 步左右开始溢出。

在第 34 步,您最终-2147483648 * -2147483648会返回 0,因此结果将始终为 0

一种解决方法是将您的方法声明更改为:

def factorial( BigInteger number ) {
于 2013-01-25T11:36:07.527 回答