Умножение длинных значений?

class Main {  
   public static void main (String[] args){  
     long value = 1024 * 1024 * 1024 * 80;  
     System.out.println(Long.MAX_VALUE);  
     System.out.println(value);  
  }  
}

Выход:

9223372036854775807
0

Правильно, если long value = 1024 * 1024 * 1024 * 80L;!


person Jonhnny Weslley    schedule 29.09.2009    source источник


Ответы (5)


В Java вся математика выполняется в самом большом типе данных, необходимом для обработки всех текущих значений. Итак, если у вас есть int * int, он всегда будет выполнять математику как целое число, но int * long выполняется как long.

В этом случае 1024*1024*1024*80 выполняется как Int, что приводит к переполнению int.

«L», конечно, заставляет один из операндов быть Int-64 (long), поэтому вся математика выполняется с сохранением значений как Long, поэтому переполнения не происходит.

person Erich    schedule 29.09.2009
comment
Арифметика, скажем, shorts выполняется не как shorts, а как ints. - person Tom Hawtin - tackline; 30.09.2009
comment
Том: Это очень интересно, я никогда этого не знал. Я только что протестировал его с двумя шортами (в С#, но аналогичное действие), и он ДЕЙСТВИТЕЛЬНО выполнял математику как целое число... Должно быть, он просто использует Int в качестве значения по умолчанию для простых числовых типов. - person Erich; 30.09.2009
comment
то есть короткий х = 0; короткий у = 0; х = х + у; выдаст ошибку несоответствия типа. - person urmalp; 30.09.2009
comment
Prateek: Это не так, компилятор достаточно умен, чтобы сделать различие. - person Erich; 30.09.2009
comment
Праттек: Там происходит некоторая целевая типизация. Вы также можете сделать myShort += anotherShort;, но не myShort = myShort + anotherShort;. Мне нравятся целые числа произвольной точности... - person Tom Hawtin - tackline; 30.09.2009
comment
Эрих: Целочисленная арифметика без long выполняется как int. Арифметика с плавающей запятой без double выполняется как float (думаю, я забыл, что происходит, когда вы делаете long+float). Мне все еще нравится арифметика произвольной точности. - person Tom Hawtin - tackline; 30.09.2009
comment
На самом деле это звучит знакомо, и это довольно надежное правило, и вполне логично, что так и должно быть. Я думаю, что long+float выполняется как двойной, поэтому вы можете сделать 5/3.0 и заставить его работать. - person Erich; 30.09.2009
comment
ваше объяснение недействительно. Если ваш номер длинный, вам нужно добавить L в конце номера большого размера. Действительно -> 31536000000L*2 . Неверный -› 31536000000*2; [поскольку L не добавлен]. - person surbhi bakshi; 23.11.2019
comment
Более того, 1000*60*60*24*365 л дает другой результат, чем 1000*60*60*24*365*1 л. Так как умножение начинается с L на R, 1000*60*60*24 -> дает целое число, а когда вы умножаете его на 365L, в результате получается long. Но когда вы умножаете его на 365 -> вывод больше 32 бит [36 бит], и компилятор удаляет все лишние 4 бита и снова делает его 32-битным, а затем умножает его на 1L, что приводит к недопустимому результату. - person surbhi bakshi; 23.11.2019

Целочисленные литералы ints. Переполнение ints. Используйте суффикс L.

long value = 1024L * 1024L * 1024L * 80L;

Если данные поступили из переменных, либо приведите их, либо заранее присвойте longs.

long value = (long)a * (long)b;

long aL = a;
long bL = b;
long value = aL*bL

Строго говоря, вам может сойти с рук меньшее количество, но, вероятно, лучше быть ясным.

Также нельзя спутать суффикс l в нижнем регистре с 1.

person Tom Hawtin - tackline    schedule 29.09.2009

Я подозреваю, что это потому, что по умолчанию java обрабатывает литералы как целые числа, а не как длинные. Итак, без L на 80 умножение переполняется.

person developmentalinsanity    schedule 29.09.2009

Этот код:

long value = 1024 * 1024 * 1024 * 80; 

умножает несколько целых чисел, преобразует их в тип long и затем присваивает результат переменной. Фактическое умножение будет выполнено javac, а не при его запуске.

Поскольку int имеет длину 32 бита, значение упаковывается и в результате получается ноль.

Как вы говорите, использование длинных значений в правой части даст результат, который переносится только в том случае, если он превышает 64 бита.

person Pete Kirkham    schedule 29.09.2009

Если я правильно понял, по вашему требованию вы хотели умножить эти значения 1024 * 1024 * 1024 * 80;

В калькуляторе я вижу значения 1024 * 1024 * 1024 * 80 = 85899345920.

Вот ваш java-код: это расчет денежной стоимости в java.

import java.math.BigDecimal;
public class Demo {
    public static void main(String[] args) {
        BigDecimal bd1 = new BigDecimal("1024");
        BigDecimal bd2 = new BigDecimal("1024");
        BigDecimal bd3 = new BigDecimal("1024");
        BigDecimal bd4 = new BigDecimal("80");
        BigDecimal bd5 = bd1.multiply(bd2).multiply(bd3).multiply(bd4);
        System.out.println(bd5); // output comes: 85899345920
    }
}
person Pra_A    schedule 24.04.2015