除以零的结果是什么?

时间:2011-11-06 23:55:14

标签: theory divide-by-zero

要清楚,我不是在寻找NaN或无穷大,或者询问x/0的答案应该是什么。我正在寻找的是:

基于如何在硬件中执行除法(我不知道它是如何完成的),如果要使用0的除数执行除法,并且处理器只是愉快地通过操作,那将会产生什么结果。它?

我意识到这很大程度上取决于股息,所以对于一个具体的答案我会问:如果计算机遵循42 / 0上的标准除法运算,计算机会吐出什么?

更新

我会尽量更清楚一点。我问的是在位级别用数字完成的实际操作是为了达到解决方案。操作的结果只是位。当发现除数为零时,NaN和错误/异常发挥作用。如果分裂实际发生了,会出现什么位?

8 个答案:

答案 0 :(得分:12)

它可能只是没有停止。整数除法可以通过重复减法在线性时间内进行:对于7/2,你可以从7中减去2总共3次,这是商,余数(模数)是1.如果你要提供一个将0除以这样的算法,除非有一个机制来防止它,算法不会停止:你可以无限次地从42中减去0,而不会到达任何地方。

从类型的角度来看,这应该是直观的。未定义计算非停顿计算结果是⊥(“底部”),每个类型的未定义值。除零没有在整数上定义,因此它应该通过引发错误或未能终止来正确地产生⊥。前者可能更可取。 ;)

其他更有效(对数时间)除法算法依赖于收敛于商的序列;对于0的红利,据我所知,这些将无法收敛(即无法终止)或产生0.请参阅维基百科上的Division

浮点除法同样需要一个特例:划分两个浮点数,减去它们的指数并对它们的有效数进行整数除法。相同的底层算法,同样的问题。这就是IEEE-754中正负无穷大的表示,以及零和NaN(0/0)的表示。

答案 1 :(得分:8)

对于具有内部“除”指令的处理器,例如带有div的x86,如果尝试除以零,CPU实际上会导致软件中断。此软件中断通常由语言运行时捕获并转换为适当的“除以零”异常。

答案 2 :(得分:5)

硬件分频器通常使用流水线long division结构。

假设我们现在谈的是整数除法(而不是浮点);长除法的第一步是对齐最重要的一步(在试图从除数中减去除数之前)。显然,在0的情况下这是未定义的,所以谁知道硬件会做什么。如果我们假设它做了一些正确的事情,下一步是执行log(n)减法(其中n是位位置的数量)。对于导致正结果的每个减法,在输出字中设置1。因此,此步骤的输出将是一个全1字。

浮点除法需要三个步骤:

  • 取得指数差异
  • mantissas的定点分割
  • 处理特殊情况

0由全0(尾数和指数)表示。然而,在尾数中始终存在隐含的前导1,因此如果我们不将此表示视为特殊情况,那么它看起来和行为就像是2的极小功率。

答案 3 :(得分:2)

这取决于实施。 IEE标准754浮点[1]定义有符号无穷大值,因此理论上应该是除零的结果。如果在分割操作中Demoninator为零,硬件只会设置一个标志。没有魔力。

一些错误的(读取x86)体系结构如果它们达到零除以理论上是一个陷阱,从数学的角度看,这是一个警察。

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

答案 4 :(得分:1)

这将是一个无限循环。通常,除法是通过连续减法完成的,就像通过连续加法进行乘法一样。

所以,零是特殊的,因为我们都知道答案是什么。

答案 5 :(得分:1)

它实际上会吐出异常。数学上,42/0是未定义的,因此计算机不会向这些输入吐出特定值。我知道除法可以在硬件中完成,但设计良好的硬件会有某种标志或中断告诉你,寄存器中包含的任何值都应该包含结果无效。许多计算机都是例外。

答案 6 :(得分:1)

在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

How to run this code in detail || 32-bit version

DIV指令的英特尔文档没有说常规输出寄存器(ax ==结果,dx ==模块)被修改,所以我认为这意味着它们保持不变。 / p> 然后,Linux将处理该中断,将SIGFPE发送到执行该操作的进程,如果不处理,将会终止该进程。

答案 7 :(得分:-1)

X / 0其中X是实数的元素并且大于或等于1, 因此X / 0 =无穷大的答案。

分区方法(c#)

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;