Каков результат деления на ноль?

Чтобы быть ясным, я не ищу NaN или бесконечность, или спрашиваю, каков должен быть ответ x/0. Я ищу:

Основываясь на том, как деление выполняется на аппаратном уровне (я не знаю, как это делается), если деление должно выполняться с делителем 0, а процессор просто прервался успешно с помощью операции, что бы вышло из это?

Я понимаю, что это сильно зависит от дивиденда, поэтому для конкретного ответа я спрашиваю: что бы компьютер выплюнул, если он выполнил свою стандартную операцию деления на 42 / 0?

Update:

Я постараюсь быть немного понятнее. Я спрашиваю о фактических операциях с номерами на уровне бит, чтобы достичь решения. Результатом операции является просто бит. NaN и ошибки/исключения вступают в игру, когда делитель обнаруживается равным нулю. Если деление действительно произошло, какие биты выйдут?

Ответ 1

Он может просто не остановиться. Целочисленное деление может выполняться в линейном времени с помощью повторного вычитания: для 7/2 вы можете вычесть 2 из 7 в общей сложности 3 раза, так что частное, а остаток (модуль) равен 1. Если вы должны были предоставить дивиденд от 0 до такого алгоритма, если не было механизма для его предотвращения, алгоритм не остановится: вы можете вычесть 0 из 42 бесконечное количество раз, не достигнув нигде.

С точки зрения типа это должно быть интуитивно понятным. Результатом вычисления undefined или без остановки является ⊥ ( "bottom" ), значение undefined, обитающее в каждом типе. Деление на ноль не определено для целых чисел, поэтому оно должно по праву производить ⊥ путем поднятия ошибки или отказа от ее завершения. Первое, вероятно, предпочтительнее.;)

Другие, более эффективные (логарифмическое время) алгоритмы деления основаны на рядах, которые сходятся к частному; для дивиденда 0, насколько я могу судить, они либо не сходятся (т.е. не заканчиваются), либо производят 0. См. Division в Википедии.

Тождество с плавающей запятой аналогично нуждается в специальном случае: чтобы разделить два поплавка, вычесть их показатели и целое число - делить их значения. Тот же базовый алгоритм, та же проблема. Вот почему существуют представления в IEEE-754 для положительной и отрицательной бесконечности, а также подписанные ноль и NaN (для 0/0).

Ответ 2

Для процессоров с внутренней инструкцией "разделить", такой как x86 с div, CPU фактически вызывает прерывание программного обеспечения, если попытаться делить на ноль. Это прерывание программного обеспечения обычно захватывается языковой средой выполнения и переводится в соответствующее исключение "Разделить на ноль".

Ответ 3

Аппаратные разделители обычно используют конвейерную структуру long division.

Предполагая, что мы говорим о целочисленном делении на данный момент (в отличие от плавающей точки); первым шагом в длинном делении является выравнивание наиболее значимых (прежде чем пытаться вычесть дивизор из дивиденда). Очевидно, что это undefined в случае 0, поэтому кто знает, что будет делать аппаратное обеспечение. Если мы предположим, что это делает что-то разумное, следующим шагом будет выполнение log (n) вычитаний (где n - количество бит позиций). Для каждого вычитания, которое приводит к положительному результату, в выходном слове устанавливается значение 1. Таким образом, выход этого шага будет состоять из слова all-1s.

Деление с плавающей запятой требует трех шагов:

  • Принимая разницу показателей
  • Фиксированное деление мантисс
  • Обработка особых случаев

0 представляется все-0s (как мантисса, так и экспонента). Однако в мантиссе всегда подразумевается ведущий 1, поэтому, если бы мы не рассматривали это представление как частный случай, оно просто выглядело бы и действовало бы как очень малая сила 2.

Ответ 4

Это зависит от реализации. Стандарт IEE 754 с плавающей запятой [1] определяет знаковые значения бесконечности, поэтому теоретически это должно быть результатом деления на ноль. Аппаратное обеспечение просто устанавливает флаг, если демонатор равен нулю при операции деления. Магии нет.

Некоторые ошибочные (читай x86) архитектуры бросают ловушку, если они попадают в деление на ноль, что теоретически, с математической точки зрения, из-за ошибки.

[1] http://en.wikipedia.org/wiki/IEEE_754-2008

Ответ 5

Это был бы бесконечный цикл. Как правило, деление осуществляется посредством непрерывного вычитания, подобно тому, как умножение выполняется посредством непрерывного добавления.

Итак, нуль является специальным, поскольку мы все знаем, что ответ в любом случае.

Ответ 6

На самом деле это исключало бы исключение. Математически 42/0, undefined, поэтому компьютеры не будут выплевывать определенное значение для этих входов. Я знаю, что разделение может быть выполнено на аппаратном уровне, но хорошо спроектированное оборудование будет иметь какой-то флаг или прерывание, чтобы сказать вам, что любое значение, содержащееся в регистрах, которые должны содержать результат, недопустимо. Из-за этого многие компьютеры делают исключение.

Ответ 7

На x86 происходит прерывание 0, а выходные регистры не изменяются

Минимальный пример 16-битного реального режима (например, добавляется к загрузчику):

    movw $handler, 0x00
    movw %cs, 0x02
    mov $0, %ax
    div %ax
    /* After iret, we come here. */
    hlt
handler:
    /* After div, we come here. *
    iret

Как выполнить этот код в деталях || 32-разрядная версия.

Документация Intel для инструкции DIV не говорит о том, что регулярные выходные регистры (ax == result, dx == module) изменены, поэтому я думаю, что это означает, что они остаются неизменными.

Затем Linux обработает это прерывание, чтобы отправить SIGFPE в процесс, который сделал это, а это будет убивать, если не обрабатываться.

Ответ 8

X/0, где X - элемент вещественных чисел и больше или равно 1, поэтому ответ X/0 = бесконечность.

Метод разделения (С#)

Int Counter = 0; /* used to keep track of the division */
Int X = 42;      /* number */
Int Y = 0;       /* divisor */
While (x > 0) { 
    X = X - Y; 
    Counter++;
}
Int answer = Counter;