简体   繁体   English

除零预防

[英]Divide by zero prevention

What is 1.#INF and why does casting to a float or double prevent a division by 0 of crashing? 什么是1.#INF以及为什么投射floatdouble防止0崩溃?
Also, any great ideas of how to prevent division by 0? 还有,如何防止0分裂的任何好主意? (Like any macro or template)? (像任何宏或模板一样)?

int nQuota = 0;

int nZero = 3 / nQuota; //crash
cout << nZero << endl;

float fZero = 2 / nQuota; //crash
cout << fZero << endl;

if I use instead: 如果我改用:

int nZero = 3 / (float)nQuota;
cout << nZero << endl;
//Output = -2147483648

float fZero = 2 / (float)nQuota;
cout << fZero << endl;
//Output = 1.#INF

1.#INF is positive infinity. 1.#INF是正无穷大。 You will get it when you divide a positive float by zero (if you divide the float zero itself by zero, then the result will be "not a number"). 当你将正浮点数除以零时,你会得到它(如果你将浮点数零本身除以零,那么结果将是“不是数字”)。

On the other hand, if you divide an integer by zero, the program will crash. 另一方面,如果将整数除以零,程序将崩溃。

The reason float fZero = 2 / nQuota; float fZero = 2 / nQuota; crashes is because both operands of the / operator are integers, so the division is performed on integers. 崩溃是因为/运算符的两个操作数都是整数,所以除法是对整数执行的。 It doesn't matter that you then store the result in a float; 然后将结果存储在浮点数中并不重要; C++ has no notion of target typing. C ++没有目标类型的概念。

Why positive infinity cast to an integer is the smallest integer, I have no idea. 为什么正整数转换为整数是最小的整数,我不知道。

Wwhy using (float) or (double) prevents a division by 0 of crashing? 使用(浮点)或(双)的Wwhy可以防止0崩溃?

It doesn't necessarily. 它不一定。 The standard is amazing spare when it comes to floating point. 在浮点时,标准是惊人的备用。 Most systems use the IEEE floating point standard nowadays, and that says that the default action for division by zero is to return ±infinity rather than crash. 现在大多数系统都使用IEEE浮点标准,并且表示除以零的默认操作是返回±无穷大而不是崩溃。 You can make it crash by enabling the appropriate floating point exceptions. 您可以通过启用适当的浮点异常使其崩溃。

Note well: The only thing the floating point exception model and the C++ exception model have in common is the word "exception". 注意:浮点异常模型和C ++异常模型的唯一共同点是“异常”一词。 On every machine I work on, a floating point exception does not throw a C++ exception. 在我工作的每台机器上,浮点异常不会引发C ++异常。

Also, any great ideas of how to prevent division by 0? 还有,如何防止0分裂的任何好主意?

  1. Simple answer: Don't do it. 简单回答:不要这样做。
    This is one of those "Doctor, doctor it hurts when I do this!" 这是其中一个“博士,医生,当我这样做时疼!” kinds of situations. 各种情况。 So don't do it! 所以不要这样做!

  2. Make sure that the divisor is not zero. 确保除数不为零。
    Do sanity checks on divisors that are user inputs. 对用户输入的除数进行完整性检查。 Always filter your user inputs for sanity. 始终过滤用户输入以获得理智。 A user input value of zero when the number is supposed to be in the millions will cause all kinds of havoc besides overflow. 当数量应该是数百万时,用户输入值为零将导致除溢出之外的各种破坏。 Do sanity checks on intermediate values. 对中间值进行健全性检查。

  3. Enable floating point exceptions. 启用浮点异常。
    Making the default behavior to allow errors (and these are almost always errors) to go through unchecked was IMHO a big mistake on the part of the standards committee. 让默认行为允许错误(这些几乎总是错误)经过不加检查是恕我直言,这是标准委员会的一个重大错误。 Use the default and those infinities and not-a-numbers will eventually turn everything into an Inf or a NaN. 使用默认值,那些无穷大而非数字最终会将所有内容变为Inf或NaN。
    The default should have been to stop floating point errors in their tracks, with an option to allow things like 1.0/0.0 and 0.0/0.0 to take place. 默认应该是在其轨道中停止浮点错误,并允许选项允许发生1.0 / 0.0和0.0 / 0.0之类的事情。 That isn't the case, so you have to enable those traps. 情况并非如此,因此您必须启用这些陷阱。 Do that and you can oftentimes find the cause of the problem in short order. 这样做,你可以经常在短时间内找到问题的原因。

  4. Write custom divide, custom multiply, custom square root, custom sine, ... functions. 编写自定义除法,自定义乘法,自定义平方根,自定义正弦,...函数。
    This unfortunately is the route that many safety critical software systems must take. 不幸的是,这是许多安全关键软件系统必须采用的途径。 It is a royal pain. 这是一种皇室的痛苦。 Option #1 is out because it's just wishful thinking. 选项#1已经出局,因为它只是一厢情愿的想法。 Option #3 is out because the system cannot be allowed to crash. 选项#3已淘汰,因为系统无法崩溃。 Option #2 is still a good idea, but it doesn't always work because bad data always has a way of sneaking in. It's Murphy's law. 选项#2仍然是一个好主意,但它并不总是有效,因为糟糕的数据总是有一种偷偷摸摸的方式。这是墨菲定律。

BTW, the problem is a bit worse than just division by zero. 顺便说一下,这个问题比仅仅除零更糟糕。 10 200 /10 -200 will also overflow. 1010分之200-200也会溢出。

You usually check to make sure you aren't dividing by zero. 您通常会检查以确保您没有除以零。 The code below isn't particularly useful unless nQuota has a legitimate value but it does prevent crashes 除非nQuota具有合法值,否则下面的代码不是特别有用,但它确实可以防止崩溃

int nQuota = 0;
int nZero = 0;
float fZero = 0;
if (nQuota)
    nZero = 3 / nQuota;
cout << nZero << endl;

if (nQuota)
    fZero = 2 / nQuota;
cout << fZero << endl;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM