代码之家  ›  专栏  ›  技术社区  ›  aioobe

数字或biginteger和bigdecimal中的错误(或者这些文件的API文档中的错误)?

  •  2
  • aioobe  · 技术社区  · 14 年前

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

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

    但是, BigInteger (和) BigDecimal )重写此方法并返回它所表示的数字的整数部分的64个低位。来自的文档 大整数 例如:

    […]如果此大整数太大,无法放入长整数中,则只返回低阶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 回复  |  直到 14 年前
        1
  •  1
  •   aioobe    14 年前

    措辞 “这可能涉及舍入或截断” 在javadocs中显示 longValue() , shortValue() , charValue() byteValue() 属于 Number 很明显,“截断”的目的是 包括 重大损失 高阶 在某些情况下是比特。

    真正的问题是,术语“截断”通常意味着低阶位的丢失。(这就是我在30年前的数值分析课程中所记得的。和 Wikipedia agrees )

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

    有符号整数到整数类型t的一种收缩转换,只需丢弃除n个最低阶位以外的所有位,其中n是用于表示类型t的位数。

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

    注释

    我最初删除这个是因为我认为提交bug报告的建议可能是无效的(基于我过去对文档bug报告的经验)。但是@aioobe 提交了错误报告…(错误ID: 7000825 )

        2
  •  4
  •   Bozho    14 年前

    文件 BigInteger.longValue() 继续执行:

    请注意,此转换可能会丢失有关biginteger值的整体大小以及 返回带有相反符号的结果 .

    这将重新定义(或澄清)定义的行为 Number.longValue() . 这是很好的,尽管有时会产生误导。例如 java.util.Set 重新定义 add 方法(通过约束重复项)。如果你通过 Collection 您可能期望它保存任何值,但是具体的实现已经重新定义了这种行为。

    更新: 我查过怎么做了 Long.valueOf(Long.MAX_VALUE).intValue() 行为。它印-1。所以我假设对于浮点数来说,“舍入或截断”只是一种可能性。否则 Number 类将完全转换为实现者。所以是的-它什么也没说。我不会说有那么糟糕,但这肯定是误导。

        3
  •  2
  •   Jon Freedman    14 年前

    我看不出你的问题,这和你每次试图表示一个超出特定数字类型界限的数字时得到的垃圾有什么不同?

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

    印刷品

    9223372036854775807 -> -1
    

    您想让API告诉您,如果传递无效的输入,您将得到无效的输出吗?