Как добавить два java.lang.Numbers? - PullRequest
38 голосов
/ 27 апреля 2010

У меня есть два номера. Например:

Number a = 2;
Number b = 3;
//Following is an error:
Number c = a + b;

Почему арифметические операции не поддерживаются в Numbers? В любом случае, как бы я добавил эти два числа в Java? (Конечно, я получаю их откуда-то, и я не знаю, являются ли они Integer или float и т.д.).

Ответы [ 9 ]

21 голосов
/ 27 апреля 2010

Вы говорите, что не знаете, являются ли ваши числа целыми или плавающими ... когда вы используете класс Number, компилятор также не знает, являются ли ваши числа целыми числами, числами с плавающей запятой или чем-то другим. В результате основные математические операторы, такие как + и -, не работают; компьютер не знает, как обрабатывать значения.

НАЧАТЬ РЕДАКТИРОВАТЬ

Основываясь на обсуждении, я подумал, что пример может помочь. Компьютеры хранят числа с плавающей запятой как две части: коэффициент и показатель степени. Так, в теоретической системе 001110 может быть разбит на 0011 10 или 3 2 = 9. Но положительные целые числа хранят числа в двоичном виде, поэтому 001110 также может означать 2 + 4 + 8 = 14. Когда вы используете класс Number, вы говорите компьютеру, что не знаете, является ли число числом с плавающей запятой или целым или каким-то другим, поэтому он знает, что у него есть 001110, но не знает, означает ли это 9 или 14 или какое-то другое значение.

КОНЕЦ РЕДАКТИРОВАНИЯ

Что вы можете сделать, это сделать небольшое предположение и перейти к одному из типов, чтобы сделать математику. Таким образом, вы могли бы иметь

Number c = a.intValue() + b.intValue();

, который вы можете превратить в

Integer c = a.intValue() + b.intValue();

если вы хотите получить ошибку округления, или

Float c = a.floatValue() + b.floatValue();

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

BigDecimal c = new BigDecimal(a.floatValue()).add(new BigDecimal(b.floatValue()));
14 голосов
/ 07 мая 2015

Это также поможет создать метод, который будет обрабатывать добавление для вас. Сейчас я не знаю, какое влияние это окажет на производительность, но я предполагаю, что оно будет меньше, чем при использовании BigDecimal.

public static Number addNumbers(Number a, Number b) {
    if(a instanceof Double || b instanceof Double) {
        return a.doubleValue() + b.doubleValue();
    } else if(a instanceof Float || b instanceof Float) {
        return a.floatValue() + b.floatValue();
    } else if(a instanceof Long || b instanceof Long) {
        return a.longValue() + b.longValue();
    } else {
        return a.intValue() + b.intValue();
    }
}
9 голосов
/ 27 мая 2015

Единственный способ правильно добавить любые два типа java.lang.Number:

Number a = 2f; // Foat
Number b = 3d; // Double
Number c = new BigDecimal( a.toString() ).add( new BigDecimal( b.toString() ) );

Это работает даже для двух аргументов с другим числовым типом. Он не должен (должен?) Создавать никаких побочных эффектов, таких как переполнение или потеря точности, поскольку toString () числового типа не снижает точность.

7 голосов
/ 27 апреля 2010

java.lang.Number - это просто суперкласс всех классов-оболочек примитивных типов (см. java doc ). Используйте соответствующий тип примитива (double, int и т. Д.) Для вашей цели или соответствующий класс оболочки (Double, Integer и т.

Учтите это:

Number a = 1.5; // Actually Java creates a double and boxes it into a Double object
Number b = 1; // Same here for int -> Integer boxed

// What should the result be? If Number would do implicit casts,
// it would behave different from what Java usually does.
Number c = a + b; 

// Now that works, and you know at first glance what that code does.
// Nice explicit casts like you usually use in Java.
// The result is of course again a double that is boxed into a Double object
Number d = a.doubleValue() + (double)b.intValue();
3 голосов
/ 27 апреля 2010

Я думаю, у вашего вопроса есть две стороны.

Почему оператор + не поддерживается на номере?

Потому что спецификация языка Java. не указывает это, и нет перегрузки оператора. Также не существует естественного способа приведения числа во время компиляции к некоторому фундаментальному типу, и нет естественного добавления, которое можно определить для некоторых типов операций.

Почему базовые арифмические операции не поддерживаются в Number?

(скопировано из моего комментария:)

Не все подклассы могут реализовать это так, как вы ожидаете. Особенно для типов Atomic сложно определить полезный контракт, например, для добавлять.

Кроме того, добавление метода будет проблематичным, если вы попытаетесь добавить Long к Short.

3 голосов
/ 27 апреля 2010

Используйте следующее:

Number c = a.intValue() + b.intValue(); // Number is an object and not a primitive data type.

Или:

int a = 2;
int b = 3;
int c = 2 + 3;
0 голосов
/ 08 июля 2015

Лучшим ответом было бы использование утилиты с двойной диспетчеризацией до большинства известных типов (взгляните на реализацию дополнения Smalltalk)

0 голосов
/ 27 апреля 2010

Прежде всего, вы должны знать, что Number является абстрактным классом. Здесь происходит то, что когда вы создаете свои 2 и 3, они интерпретируются как примитивы, и в этом случае создается подтип (я думаю, целое число). Поскольку Integer является подтипом Number, вы можете назначить вновь созданное Integer в ссылку на Number.

Однако число - это просто абстракция. Это может быть целое число, это может быть число с плавающей запятой и т. Д., Поэтому семантика математических операций будет неоднозначной.

Число не обеспечивает классические операции с картами по двум причинам:

Во-первых, методы-члены в Java не могут быть операторами. Это не C ++. В лучшем случае они могут предоставить add ()

Во-вторых, выяснить, какой тип операции нужно выполнять, когда у вас есть два входа (например, деление числа с плавающей точкой на int), довольно сложно.

Таким образом, вместо этого вы несете ответственность за преобразование обратно в конкретный примитивный тип, который вас интересует, и применяете математические операторы.

0 голосов
/ 27 апреля 2010

Number - это класс abstract, экземпляр которого нельзя создать. Если у вас есть правильный экземпляр, вы можете получить number.longValue() или number.intValue() и добавить их.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...