Почему деление на ноль является неисправимой проблемой? - PullRequest
1 голос
/ 29 сентября 2010

Почему ява не может изящно вернуть какое-то значение с делением на ноль и вместо этого должна выдать исключение?

Я получаю ArrayIndexOutOfBoundsException:0 Это связано с тем, что повреждение, на самом деле, представляет собой массив значений, в котором хранится много разных «повреждений».

В Java я пытаюсь создать индикатор выполнения. Наш пример: урон, нанесенный в гоночной игре, путем установки значения высоты в процентах от максимально допустимого урона до начала игры.

При запуске программы damageTaken = 0;

(damageTaken / maximumDamage)

даст числа от 0 до 1.

Затем я просто умножаю это на высоту индикатора выполнения, чтобы создать панель заливки соответствующей высоты.

Программа вылетает. Я хочу, чтобы индикатор выполнения был нулевой высоты!

Ответы [ 5 ]

13 голосов
/ 29 сентября 2010

Вы не делите на ноль, вы делите ноль на что-то .

Полностью занято две половины нуля. Ответ ноль. Скажем, у вас ноль яблок. Ты разделил свои нулевые яблоки между Алисой и Бобом. У Алисы и Боба теперь нет яблок.

Но вы не можете делить на ноль. Скажем, у вас есть два яблока. Теперь вы хотите дать эти яблоки нулевым людям. Сколько яблок получает каждый человек? Ответ не определен, поэтому деление на ноль невозможно.

6 голосов
/ 29 сентября 2010
(damageTaken / maximumDamage)

Это дает вам деление на ноль, исключение, только если maximumDamage равно нулю.

Если damageTaken равно нулю, проблем нет.

3 голосов
/ 29 сентября 2010

Просто добавьте специальный регистр для 0;

private int getProgress()
    if (damageTaken == 0) {
        return 0;
    } else {
        return (damageTaken / maximumDamage) * progress.getHeight();
    }
}

Однако , (и это большое значение) причина, по которой вы получаете деление на 0, заключается в том, что maximumDamage равно 0, не damageTaken.Итак, что вы, вероятно, действительно хотите:

private int getProgress()
    if (maximumDamage== 0) {
        return 0;
    } else {
        return (damageTaken / maximumDamage) * progress.getHeight();
    }
}
0 голосов
/ 22 января 2014

Концептуально иметь 4/0, чтобы получить произвольное число, было бы не хуже, чем попытка удвоить счет 2000000000, чтобы получить счет -294967296. Однако большинство процессоров игнорирует большинство видов арифметического переполнения, если только один явно не проверяет это, но не может игнорировать попытку деления на ноль, если только один не проверяет заранее операнды заранее (и пропускает операцию, если они недопустимы). Учитывая, что многие процессоры имеют флаги «переполнения», ничто не помешает процессору указать, что попытка деления на ноль просто не должна делать ничего, кроме установки флага переполнения (успешная операция деления должна его очистить); код, который хочет вызвать исключение в таком случае, может сделать это.

Я подозреваю, что причина различного поведения связана с ранними днями работы на компьютере; Аппаратные средства для инструкции деления могли судить, что она была завершена, когда остаток был меньше делителя. Если этого никогда не произойдет, инструкция может остановиться, пока общая схема контрольных часов (предназначенная для оповещения о сбое, если по какой-либо причине команды перестают выполняться) не отключится. Аппаратные средства для обнаружения проблемы и выхода без остановки процессора были бы тривиальными по сегодняшним стандартам, но в те дни, когда компьютеры были построены из дискретных транзисторов, это было дешевле и почти столь же эффективно, чтобы программисты не пытались делить ноль, когда-либо .

0 голосов
/ 29 сентября 2010

Давайте перестанем говорить о незаконности, как будто математическая полиция собиралась штурмовать комнату.;) По математическим соображениям, стоящим за этим, этот связанный вопрос полезен.

Справедливо спросить, почему после всего этого времени современные платформы программирования не обрабатывают деление наноль ошибок для нас каким-то стандартным способом - но для ответа на вопрос: Java, как и большинство других платформ, выдает ошибку, когда происходит деление на ноль.В общем, вы можете либо:

  • Обрабатывать до: проверьте переменную, которая будет использоваться в качестве вашего знаменателя для нуля перед выполнением деления
  • Обрабатывать после: выможет поймать исключение, которое выдается, когда происходит деление на ноль, и обрабатывать его корректно.

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

Так что да, вам нужен особый случай, чтобы справиться с этой ситуацией.Добро пожаловать в программирование.;)

...