Number或BigInteger和BigDecimal中的错误(或者在那些API文档中)?

时间:2010-11-17 12:03:05

标签: java biginteger bigdecimal

根据Number.longValue()的规范,该方法应该......

  

以long形式返回指定数字的值。这可能涉及舍入或截断。

但是,BigInteger(和BigDecimal)会覆盖此方法,并返回它所代表的数字的整数部分的64位低位。例如,来自BigInteger的文档:

  

[...]如果这个BigInteger太大而不适合长,只返回低位64位。[...]

我声称“这可能涉及舍入或截断。”并未说任何关于实际应该返回的方法,或者,实施或文档中存在错误。

您同意,还是我的推理错误?


示例代码:

import java.math.BigInteger;
import static java.math.BigInteger.*;

public class Main {
    public static void main(String[] args) {

        BigInteger i = valueOf(Long.MAX_VALUE);

        // Result: Long.MAX_VALUE, just as expected.
        Number n1 = i;
        System.out.println(n1 + " -> " + n1.longValue());

        // I expect to get the "rounded" value Long.MAX_VALUE
        Number n2 = i.add(ONE);
        System.out.println(n2 + " -> " + n2.longValue());

        // I expect to get the "rounded" value Long.MAX_VALUE
        Number n3 = i.multiply(TEN);
        System.out.println(n3 + " -> " + n3.longValue());
    }
}

输出:

9223372036854775807 -> 9223372036854775807
9223372036854775808 -> -9223372036854775808
92233720368547758070 -> -10

3 个答案:

答案 0 :(得分:4)

BigInteger.longValue()的文档继续:

  

请注意,此转换可能会丢失有关BigInteger值整体幅度的信息,以及返回符号相反的结果

这重新定义(或澄清)Number.longValue()定义的行为。这很好,虽然有时会产生误导。例如,java.util.Set重新定义了add方法的行为(通过约束重复项)。如果您传递Collection,您可能希望它包含任何值,但具体实现已重新定义此行为。

更新:我检查了Long.valueOf(Long.MAX_VALUE).intValue()的行为方式。它打印-1。所以我假设通过" round或truncate"关于浮点数,这只是一种可能性。否则,Number类将完全转换的方式留给实现者。所以是的 - 它没有说明任何事情。我不会说它那么糟糕,但肯定会产生误导。

答案 1 :(得分:2)

我没有看到你的问题,这与你在尝试表示特定数字类型范围之外的数字时得到的垃圾有什么不同?

final Number n = Long.MAX_VALUE;
System.out.println(n + " -> " + n.intValue());

打印

9223372036854775807 -> -1

如果传递无效输入,您是否希望API告诉您输出无效?

答案 2 :(得分:1)

措辞“这可能涉及舍入或截断”出现在longValue()shortValue()charValue()byteValue()的javadoc中Number,所以很明显,“截断”旨在包含在某些情况下高阶位的丢失。

问题实际上是术语“截断”通常意味着丢失较低阶位。 (这就是我30年前的数值分析课程中的记忆。Wikipedia agrees

相比之下,JLS 5.1.3描述了相同的过程(当缩小整数基元类型时)如下:

  

将有符号整数缩小为整数类型T只会丢弃除n个最低位之外的所有位,其中n是用于表示类型T的位数。

是的,我同意javadoc是不正确的。提交错误报告。

注意

我最初删除了这个,因为我认为我提交错误报告的建议可能是徒劳的(根据我过去的文档错误报告经验)。但是@aioobe 已经提交了错误报告......(错误ID:7000825