Java арифметика int vs. long - PullRequest
12 голосов
/ 19 июня 2010

Я провел поиск в Google, но не могу найти то, что ищу. Я пытаюсь найти некоторую подробную информацию о том, как работает арифметика в Java. Например, если вы добавляете два длинных слова вместе, используется ли тот же оператор сложения, который используется при добавлении двух целых чисел? Кроме того, что происходит под капотом, когда вы смешиваете длинные и целые числа в арифметических выражениях, таких как:

long result;
long operand a = 1;
int operand b = 999999999;

result = a + b;

Если бы кто-нибудь мог пролить свет на это или опубликовать ссылки на соответствующие статьи, это было бы здорово. Спасибо!

РЕДАКТИРОВАТЬ: Спасибо за ответы до сих пор. Кроме того, безопасно ли выполнять арифметику с различными примитивами, если вы присваиваете переменную самого широкого типа примитивов в своем выражении?

Ответы [ 6 ]

15 голосов
/ 19 июня 2010

При смешивании типов int автоматически расширяется до long, а затем добавляются два long для получения результата. Спецификация языка Java объясняет процесс для операций, содержащих различные типы примитивов.

В частности, эти типы будут расширяться каждым примитивом, не требуя приведения:

  • байт в short, int, long, float или double
  • short to int, long, float или double
  • char в int, long, float или double
  • int для long, float или double
  • долго плавать или удваивать
  • с плавающей запятой, чтобы удвоить
7 голосов
/ 19 июня 2010

См .: Конверсии и продвижения

В соответствии с этим ваше int повышается до long, а затем оценивается.

То же самое происходит с, дляэкземпляр, int + double и остальные примитивы.

System.out( 1 + 2.0 );// prints 3.0 a double

Что касается оператора сложения Я почти такой же, но у меня нет никаких ссылок на него.

AБыстрый просмотр исходного кода компилятора показывает, что они разные.

А именно iadd для сложения int и ladd для длинного добавления:

См. Этот пример кода:

$cat Addition.java 
public class Addition {
    public static void main( String [] args ) {
        int  a  = Integer.parseInt(args[0]);
        long b = Long.parseLong(args[0]);
        // int addition 
        int  c  = a + a;
        // long addition 
        long d = a + b;
    }
}
$javac Addition.java 
$

При компиляции сгенерированный байт-код выглядит так:

$javap -c Addition 
Compiled from "Addition.java"
public class Addition extends java.lang.Object{
public Addition();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   aload_0
   1:   iconst_0
   2:   aaload
   3:   invokestatic    #2; //Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
   6:   istore_1
   7:   aload_0
   8:   iconst_0
   9:   aaload
   10:  invokestatic    #3; //Method java/lang/Long.parseLong:(Ljava/lang/String;)J
   13:  lstore_2
   14:  iload_1
   15:  iload_1
   16:  iadd
   17:  istore  4
   19:  iload_1
   20:  i2l
   21:  lload_2
   22:  ladd
   23:  lstore  5
   25:  return

}

Посмотрите на строку 16 она говорит: iadd (для сложения int), в то время как строка 22 говорит ladd (для длинного сложения)

Кроме того, безопасно ли выполнять арифметику с различными примитивами, если вы присваиваете переменную самого широкого типа примитива в своем выражении?

Да, и это также «безопасно» для выполнения арифметики с меньшими размерами, в том смысле, что они не ломают программу, вы просто теряете информацию.

Например, попробуйте добавить Integer.MAX_VALUE до Integer.MAX_VALUE, чтобы увидеть, что происходит, или int x = ( int ) ( Long.MAX_VALUE - 1 );

3 голосов
/ 19 июня 2010

это называется арифметическим продвижением. подробности смотрите на http://www.cafeaulait.org/course/week2/22.html

3 голосов
/ 19 июня 2010

Кроме того, безопасно ли выполнять арифметику с различными примитивами, если вы присваиваете переменную самого широкого типа примитива в своем выражении?

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

2 голосов
/ 28 апреля 2016
int a=5;  
long b=10;  
a+=b;  
System.out.println(a);

Основное отличие состоит в том, что с a = a + b не происходит никаких типов, и поэтому компилятор злится на вас за то, что он не является типизацией.Но с a += b все, что он делает, это приведение типов b к a, совместимое с a.

1 голос
/ 22 мая 2017

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

    byte a = 1;
    short b = 1;
    System.out.println(a+b);                     //Output = 2
    Object o = a+b;                              //Object becomes int
    System.out.println(o.getClass().getName());  //Output = java.lang.Integer

    int c = 1;
    System.out.println(a+b+c);                   //Output = 3
    o = a+b+c;                                   //Object becomes int
    System.out.println(o.getClass().getName());  //Output = java.lang.Integer

    long d = 1l;
    System.out.println(a+b+c+d);                 //Output = 4
    o = a+b+c+d;                                 //Object becomes long
    System.out.println(o.getClass().getName());  //Output = java.lang.Long

    float e = 1.0f;
    System.out.println(a+b+c+d+e);               //Output = 5.0
    o = a+b+c+d+e;                               //Object becomes float
    System.out.println(o.getClass().getName());  //Output = java.lang.Float

    double f = 1.0;
    System.out.println(a+b+c+d+e+f);             //Output = 6.0
    o = a+b+c+d+e+f;                             //Object becomes double
    System.out.println(o.getClass().getName());  //Output = java.lang.Double

Ниже приведен порядок типов данных в соответствии с диапазоном в Java:

    byte<short<int<long<float<double

Это порядок, в котором будет происходить расширение.

Примечание: float имеет больший диапазон, чем long, но имеет меньший размер.

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