Почему это не приводит к 1000?

Возможный дубликат:
Проблема с Java. В чем причина и каковы вероятные результаты

long milli=24*60*60*1000;
long micro=24*60*60*1000*1000;
long result=micro/milli;

Результат должен быть 1000, но это не так. Почему это работает, когда я использую 24*60*60*1000*1000L?

Может ли кто-нибудь сказать мне причину этого?


person Rakesh    schedule 18.02.2011    source источник
comment
Какой результат вы получаете вместо этого?   -  person payne    schedule 18.02.2011
comment
Повторить вашего предыдущего вопроса сегодня, который также содержит ответ.   -  person Johan Sjöberg    schedule 18.02.2011
comment
вы выходите за пределы диапазона int, вам нужно указать VM использовать long.   -  person Nishant    schedule 18.02.2011
comment
Этот вопрос слишком легкий, пока я печатал свой, было еще четыре ответа...   -  person Paŭlo Ebermann    schedule 18.02.2011
comment
@Paulo, на первый пост тоже был ответ. ;)   -  person Peter Lawrey    schedule 18.02.2011
comment
Я чувствую, что это немного моя вина. Ракеш добавил новый вопрос к своему исходному сообщению в форме редактирования - Любой может рассказать мне о VM... передача чисел в JAVA - я сказал ему, что если он хочет, чтобы этот вопрос был замечен, он должен задать новый вопрос . Либо я не понял, либо он не понял :С   -  person Rich    schedule 18.02.2011
comment
@Рич - спасибо! Я отредактировал сообщение, чтобы удалить свой -1 (и сделал это).   -  person Andreas Dolk    schedule 18.02.2011


Ответы (7)


Проблема в том, что вычисление выполняется для ints, а затем приводится к long, и, к сожалению, 24*60*60*1000*1000 не помещается в int и зацикливается. Вы можете сделать что-то вроде

long micro=24L*60*60*1000*1000;

чтобы заставить последнее умножение выполняться на длинных.

person andri    schedule 18.02.2011
comment
Чтобы добавить к этому (правильному) ответу: поскольку все термины в правой части являются целыми числами, арифметика, включая переполнение, будет выполняться над целыми числами. Затем результат будет преобразован в long. Добавляя 'L' или (long) справа, вы вызываете расширяющее преобразование всех целых чисел в long (до того, как оно переполнится), и результат не будет переполнен. - person Erik; 18.02.2011

Легко, если знаешь, но всегда сюрприз ;)

Литерал 1000 является значением int, поэтому умножение выполняется с целыми числами, а не с длинными.

long micro=24*60*60*1000*1000;

интерпретируется как

long micro = (long) ((int) 24*60*60*1000*1000);

что 500654080 вместо 86400000000

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

long milli=24*60*60*1000;
long micro=24*60*60*1000*1000 * 1L; // forces a calculation in long
long result=micro/milli;
person Andreas Dolk    schedule 18.02.2011

Возможно, 24*60*60*1000*1000 обрабатывается как int и усекается.

Чтобы заставить его рассматриваться как длинное, сделайте одно (или все) число длинным, добавив к нему суффикс L:

24L*60L*60L*1000L*1000L
person Adrian Pronk    schedule 18.02.2011

Когда вы говорите Java умножать значения int (а литералы целых чисел всегда имеют тип int, если вы не добавляете l или L), то результат всегда также будет типа int. 24*60*60*1000*1000 приводит к переполнению, поскольку оно больше, чем максимально возможное значение int (Integer.MAX_VALUE).

Затем (после того, как переполнение было «разрешено» путем вырезания старших значащих битов), значение присваивается значению long.

Указание одного из чисел как long (1000L) означает, что целое умножение выполняется с long числами.

person Joachim Sauer    schedule 18.02.2011
comment
joachim спасибо за помощь....такой же вопрос 2) int i=0; for(a=0;a‹=integer.MAX_VAL;a++) { i++; } СОП(i); Обычно это переходило в бесконечный цикл, потому что, поскольку есть максимальное значение, оно должно выйти из цикла. При каких условиях он будет выполнен успешно и какое значение будет исключено. пожалуйста, помогите мне ... там сказано, что обе проблемы связаны с одной и той же концепцией ... я не могу найти помощь мне - person Rakesh; 18.02.2011
comment
@Rakesh: пожалуйста, задайте это как отдельный вопрос, комментарии не совсем правильное место для такого рода дискуссий. - person Joachim Sauer; 18.02.2011

Ваша проблема здесь в том, что тип данных int поддерживает числа только до 2000000000, в то время как ваше число составляет 86400000000, что примерно в 40 раз больше этого числа. Таким образом, ваше умножение зацикливается (отбрасывает старшие биты результата).

Поэтому вам нужно переключиться на следующий более крупный тип данных, long, сообщив Java, что по крайней мере одно из ваших чисел предназначено именно так:

 long micro=24*60*60*1000*1000L;

Тогда ваш результат будет правильным.

person Paŭlo Ebermann    schedule 18.02.2011

Это потому, что вы выполняете целочисленную (32-битную) арифметику, а затем преобразуете результат int в long. Поскольку числа слишком большие, это не работает.

Заменить на :

long milli=24*60*60*1000L;
long micro=24*60*60*1000*1000L;
long result=micro/milli;

чтобы заставить операции выполняться с длинными.

person JB Nizet    schedule 18.02.2011

Максимальное значение, которое может содержать int, равно Integer.MAX_VALUE, а значение вашего макроса больше, чем может содержать целое число, и расчет выполняется на целых числах, поэтому он усекается. Если вы сделаете один из множителей длинным (заканчивающимся на L или l), он будет рассчитан правильно.

long milli=24*60*60*1000;
long micro=24*60*60*1000*1000L;
long result=micro/milli;
person fmucar    schedule 18.02.2011