Исключения имеют типы, и это позволяет вам найти тип и быстро классифицировать проблему.Из документации:
ArithmeticException
: бросается при возникновении исключительного арифметического условия.Например, целое число «делить на ноль» выбрасывает экземпляр этого класса.
Более того, большинство исключений создается с сообщением, чтобы помочь вам еще больше выяснить, что произошло.
try {
int i = 0 / 0;
} catch (ArithmeticException e) {
e.printStackTrace();
}
Это печатает:
java.lang.ArithmeticException: / by zero
at [filename:line number]
Но как это произошло?
Java, как и многие другие языки программирования, различаетцелочисленное деление и деление с плавающей запятой.
Бинарный оператор /
выполняет деление, производя частное его операндов,Левый операнд - это дивиденд, а правый операнд - делитель.Целочисленное деление округляется до 0. [...] если значение делителя в целочисленном делении равно 0, то выдается ArithmeticException
.
Следующие сведения могут вас удивить, если выне знаком с целочисленным делением:
System.out.println(1/2); // prints "0"
Здесь происходит то, что поскольку дивиденд и делитель равны int
, операция представляет собой целочисленное деление, результат которого округляется до int
.Помните, что int
может содержать только целое число (ограниченного диапазона, приблизительно 4 миллиарда чисел).
Вы можете указать, что вам нужно деление с плавающей запятой, сделав хотя бы один из операндов плавающей запятойчисло.
System.out.println(1/2.0); // prints "0.5"
System.out.println(1D/2); // prints "0.5"
D
- это специальный суффикс для числового литерала, указывающий, что это точное значение double
.Также есть L
для long
(64-разрядное целое число).
Значение double
необходимо сохранить в переменной double
.
double v = 1D / 2; // v == 0.5
int i = 1D / 2; // DOESN'T COMPILE!!! Explicit cast needed!
Обратите внимание, чтоделение не имеет никакого отношения к тому, к какому типу оно в итоге придет.Это зависит только от типа делимого и делителя.
double v = 1 / 2; // v == 0.0 (!!!)
Следует также отметить, что double
также является числом с ограниченной точностью.
System.out.println(.2D + .7D - .9D); // prints "-1.1102230246251565E-16"
А как насчет моего кода?
Итак, теперь давайте сосредоточимся на том, что случилось с вашим кодом:
timeTaken = stopTime - startTime;
timeInSecs = ((timeTaken/1000));
speed = 45/timeInSecs;
Скорее всего, произошло то, что timeTaken
объявлен как long
.Следовательно, timeTaken/1000
приводит к целочисленному делению.Если timeTaken < 1000
, то результат деления будет 0
.
. На этом этапе не имеет значения, является ли timeInSecs
double
или float
, потому что целочисленное деление имеетуже было выполнено.Это означает, что timeInSecs
будет 0
или 0.0
, в зависимости от его типа.
По полученной ошибке можно определить, что timeInSecs
может быть целочисленным типом.,В противном случае 45/timeInSecs
приведет к делению с плавающей запятой, которое приведет к Infinity
(специальному значению double
) вместо броска ArithmeticException
.
Итак, как нам исправитьthis?
Мы можем исправить это, объявив переменные следующим образом:
long timeTaken;
double timeInSecs;
double speed;
И затем выполняя вычисления следующим образом (обратите внимание, что 1000
теперьdouble
значение).
timeTaken = stopTime - startTime;
timeInSecs = timeTaken/1000D;
speed = 45D/timeInSecs; // D is not necessary here, but it's good for clarity
См. Также