计算机会尝试除以零吗?


59

我们都知道0/0Undefined如果我是把它变成一个计算器返回一个错误,如果我是创建一个程序(在C至少)操作系统将终止它,当我试图除以零。

但是我一直想知道的是,计算机是否试图除以零,或者它只是具有“内置保护”,这样当它“看到” 0/0时甚至在尝试计算之前就返回错误?


10
0/0是未定义的,任何其他数字/ 0是另一种错误,您似乎将两者混淆了
edc65

7
从数学上讲,除以0的任何数字都是不确定的。
ManoDestra '16

12
@jwg:“如果确实有一个值,则为1”-不一定;有数学的分支全部投入到工作的价值可能会在不同的情况下:)
psmears

11
为了澄清这里的术语,0/0被称为不确定的形式而X / 0为非零X未定义的。最终以0/0结束的计算通常可以用不同的方式来给出真实的答案,而x / 0本质上是没有意义的。
时代

9
@jwg,那么您可能会对霍皮塔尔的规则感兴趣。肯定在某些情况下0/0并不意味着值
1。– d0nut

Answers:


74

CPU具有内置检测功能。大多数指令集体系结构都指定CPU将捕获到一个异常处理程序,以将整数除以零(我不关心除数是否为零)。

零除数的检查可能与尝试进行除法的操作在硬件中并行发生,但是,对有问题的条件的检测实际上会取消除法并捕获陷阱,因此我们无法真正确定是否有一部分它是否尝试了分裂。

(硬件通常是这样工作的,并行执行多项操作,然后选择合适的结果,因为这样每个操作都可以立即开始,而无需序列化选择合适的操作。)

当打开溢出检测功能时,也将使用相同的异常捕获机制,通常使用不同的add / sub / mul指令(或这些指令上的标志)来请求该机制。

浮点除法还内置了零除法检测功能,但是返回一个不同的值(IEEE 754指定NaN),而不是捕获到异常处理程序。


假设地说,如果CPU忽略了任何试图除以零的检测,则问题可能包括:

  • 挂起CPU(例如在inf。循环中)-如果CPU使用一种算法进行除法,该方法在分子小于除数(绝对值)时停止,则可能会发生这种情况。像这样的挂起将导致CPU崩溃。
  • 如果CPU使用计数器以最大可能的除法步数终止除法(例如,在32位计算机上为31或32),则为(可能是可预测的)无用答案。

51
@Ankush“系统崩溃”实际上并不是在CPU级别上发生的事情。没有被零除陷的CPU最可能的行为是,它仅执行除法运算,产生一些无意义的结果并继续运行。就像您将两个整数相加时会发生溢出一样。
Ixrec '16

6
对于浮点,通常可以通过翻转FPU中的标志来设置“ NaN”和“ trap”之间的选择。
Vatine '16

10
@Ankush如果lxrec所说的不清楚:就CPU而言,没有崩溃的事情。
user253751 '16

7
@Ankush很少有情况会导致CPU级别的“系统崩溃”。在那种情况下,我们谈论的是诸如热保护停机(过热保护),三重故障和类似情况之类的事情。几乎所有您在日常使用中遇到的崩溃,包括无效的操作码,都可以通过某种方式进行陷阱和恢复来处理,或者只是忽略该错误并以潜在的不干净状态继续执行,可能已设置了一些错误标志。
CVn

8
如果没有用零除陷阱,那么按照编程的说法,结果将是“未定义的行为”。这意味着计算机可以执行任何操作。正如Bergi所述,它可能会进入越野车并挂起。它可能只是输出一些未指定的位系列,这些位恰好是它们实现除法逻辑的结果(请记住,计算机在数学意义上不会“除”。它对两个数进行运算,这与除法非常接近)通常我们将其简称为“除法”。另请参见浮点舍入)。
Cort Ammon

34

这取决于语言,编译器,使用的是整数还是浮点数,等等。

对于浮点数,大多数实现使用IEEE 754标准,其中很好地定义了除以0。0/0给出NaN(非数字)的明确定义的结果,而x≠0的x / 0给出+ Infinity或-Infinity,具体取决于x的符号。

在像C,C ++等语言中,被零除会调用未定义的行为。因此,根据语言定义,任何事情都可能发生。尤其是您不想发生的事情。就像编写代码时一切正常,当客户使用代码时销毁数据一样。因此,从语言角度来看,不要这样做。某些语言可确保您的应用程序崩溃。如何实现这取决于他们。对于这些语言,除以零将崩溃。

许多处理器具有某种内置的“除法”指令,具体取决于处理器的行为。在Intel 32位和64位处理器上,当您尝试除以零时,“除法”指令将使应用程序崩溃。其他处理器的行为可能有所不同。

如果编译器在执行某些代码时检测到将被零除,并且编译器对其用户友好,则它可能会向您发出警告,并生成内置的“除”指令,从而使行为为相同。


22
“在Intel 32位和64位处理器上,当您尝试除以零时,“除法”指令将使应用程序崩溃。” 需要引用。CPU对应用程序一无所知,它们执行指令并(如果我们包括MMU,则)强制执行内存访问限制(除非在ring 0或非Intel-x86架构中等效)。该指令是应用程序A的一部分,而不是应用程序B或操作系统组件C的一部分,与CPU无关;指令可以是指令X还是使用存储器地址Y是相关的。
CVn

1
要添加到@MichaelKjörling评论中:操作系统具有通知此应用程序(以及其他类型的错误)的方法。在Windows世界中,它是其中的EXCEPTION_INT_DIVIDE_BY_ZERO值,该值EXCEPTION_RECORD将由(希望)安装的结构异常处理处理程序处理
user45891 '16

1
有时他们做的事情不是保证您的应用会崩溃。例如,许多语言/平台保证它们将被零除引发异常。然后,您可以捕获并处理所述异常而不会崩溃。
reirab '16

2
您可以在“其他处理器的行为可能有所不同”中删除“可能”:在PowerPC平台上,除以零除只会产生零结果。这比X86平台的恐慌行为有用得多。
cmaster

13

似乎您想知道如果有人制造的CPU在除法之前未明确检查零的情况会发生什么。将会发生什么完全取决于该部门的实施。在不赘述的情况下,一种实现将产生设置了所有位的结果,例如16位CPU上的65535。另一个可能挂断电话。


1

但是我一直想知道的是,计算机是否试图除以零,或者它只是具有“内置保护”,这样当它“看到” 0/0时,甚至在尝试计算之前都会返回错误?

由于x/0没有意义,所以计算机必须始终检查除以零。这里有一个问题:程序员希望进行计算(a+b)/c而不必费心检查该计算是否有意义。对于由CPU +数字类型+操作系统+语言除以0的幕后反应是要么做得太激烈(例如使程序崩溃),要么做得过分良性(例如,创建一个不使之成为零的值)。 (例如IEEE浮点数NaN,即不是数字的数字)。

在通常的情况下,程序员应该知道是否(a+b)/c有意义。在这种情况下,没有理由检查是否被零除。如果确实发生了被零除的情况,并且如果机器语言+实现语言+数据类型+操作系统对此做出的响应是使程序崩溃,则可以。如果响应是创建一个可能最终污染程序中每个数字的值,那也是可以的。

在高可靠性计算领域,“大刀阔斧”或“过度良性”都不是正确的选择。这些默认响应可能会杀死患者,使客机坠毁或在错误的地方炸弹爆炸。在高可靠性环境中,编写(a+b)/c代码的程序员会在代码审查期间被处死,或者在现代,可能会通过检查Verboten构造的工具自动将其处死。在这种环境下,该程序员应该改写一些类似的东西div(add(a,b),c)(可能还需要检查错误状态)。在引擎盖下,div(以及add)函数/宏可防止被零除(或的情况下溢出add)。保护所需要的是非常特定于实现的。


仅仅因为NaN不遵守您在学校学习的算法,并不意味着它没有任何意义。它遵循不同的算法
Caleth

-2

我们现在知道x/0,并0/0没有明确的答案。如果0/0仍然尝试进行计算会怎样?

在现代系统上,计算被传递到CPU内的MPU,并被标记为非法操作,返回NaN

在更老的系统上,例如80年代没有片上划分的家用计算机,计算是通过运行的任何软件完成的。有几种可能的选择:

  • 减去越来越小的除数副本,直到值达到零,并跟踪减去的大小副本
    • 如果它在第一次减法之前检查零,它将迅速退出,结果将是 0
    • 如果假设它必须至少能够减去一次,则结果将是 1
  • 计算两个数字的对数,将它们相减并将e增大为结果的幂。与上述减法相比效率很低,但在数学上有效
    • 尝试计算时可能会发生溢出,log(0)并且该软件将使用其错误处理例程或崩溃
    • 该软件可能会假设可以以固定的步数计算所有对数,并返回一个很大但不正确的值。由于两个对数相同,所以差为0和e 0 = 1,结果为1

换句话说,将取决于实现方式,并且将可能编写出能够为每个值产生正确且可预测的结果的软件,但是0/0尽管如此,看起来似乎有些奇怪的值仍然是内部一致的。


3
这个问题是关于整数除以零,没有整数这样的东西NaN
David Hammen

3
没有CPU将要计算日志并减去以计算除法结果。对数指令时序比除法大几个数量级。log(0)的值是多少?
wallyk '16

1
@DavidHammen OP从未提及整数,也没有人对此问题发表评论。仅在答案中提到整数。
CJ Dennis

@wallyk我在回答中已经说过,对数very inefficient用于除法。算术成本为(加法=减法)<=乘法<=除法。如果没有MPU可以在与加法(通常是一个)相同的时钟周期数内进行除法,那么除法运算要比加法和减法昂贵,并且通常也要比乘法更昂贵。
CJ Dennis
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.