Ошибка в Number или BigInteger и BigDecimal (или, альтернативно, в документации API к ним)? - PullRequest
2 голосов
/ 17 ноября 2010

Согласно спецификации Number.longValue() метод должен ...

Возвращает значение указанного числа в виде long. Это может включать округление или усечение.

Однако BigIntegerBigDecimal) переопределяет этот метод и возвращает 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 ]

4 голосов
/ 17 ноября 2010

Документация BigInteger.longValue() продолжается с:

Обратите внимание, что это преобразование может потерять информацию об общей величине значения BigInteger, а также вернуть результат с обратным знаком .

Это переопределяет (или уточняет) поведение, определенное Number.longValue(). Это хорошо, хотя иногда вводит в заблуждение. Например, java.util.Set переопределяет поведение метода add (путем ограничения дубликатов). Если вы передадите Collection, вы можете ожидать, что он будет содержать какие-либо значения, но конкретная реализация переопределила это поведение.

Обновление: Я проверил, как ведет себя Long.valueOf(Long.MAX_VALUE).intValue(). И это печатает -1. Так что я бы предположил, что «округлять или усекать» это просто возможность, касающаяся чисел с плавающей запятой. В противном случае класс Number оставляет способ преобразования полностью для разработчиков. Так что да - это ничего не говорит об этом. Я бы не сказал, что это так плохо, но это, безусловно, вводит в заблуждение.

2 голосов
/ 17 ноября 2010

Я не вижу вашего вопроса, как это отличается от мусора, который вы получаете, когда пытаетесь представить число за пределами определенного числового типа?

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

печать

9223372036854775807 -> -1

Хотите ли вы, чтобы API сообщал вам, что вы получите неверный вывод, если передадите неверный ввод?

1 голос
/ 17 ноября 2010

Формулировка «Это может включать округление или усечение» появляется в javadocs для longValue(), shortValue(), charValue() и byteValue() из NumberТаким образом, ясно, что «усечение» предназначено для включения потери значительных старших битов в некоторых случаях.

Проблема на самом деле заключается в том, что термин «усечение»«условно означает потерю младших битов.(Вот как я помню это из моего курса численного анализа 30 лет назад. И Википедия соглашается .)

В отличие от этого, JLS 5.1.3 описывает то же самоеобрабатывают (при сужении целочисленных примитивных типов) следующим образом:

При сужающемся преобразовании целого числа со знаком в целочисленный тип T просто отбрасываются все, кроме n младших битов, где n - количество используемых битовпредставлять тип T.

Так что да, я согласен, что Javadoc является неправильным.Отправьте отчет об ошибке.

ПРИМЕЧАНИЕ

Я первоначально удалил это, потому что я думал, что мое предложение представить отчет об ошибке было, вероятно, бесполезным (основываясь на моем предыдущем опыте с документациейотчеты об ошибках).Но @aioobe отправил отчет об ошибке ... (идентификатор ошибки: 7000825 )

...