Java try-catch 除以零
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2259190/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
try-catch for division by zero
提问by Firat
My question is about try-catch blocks on a simple division by zero example. You see the first line of try? If I cast any of those two variables to the double the program does not recognize the catch block. In my opinion, whether I cast or not only the catch block must be executed. What is wrong on this code?
我的问题是关于简单除以零示例的 try-catch 块。你看到 try 的第一行了吗?如果我将这两个变量中的任何一个强制转换为 double,程序将无法识别 catch 块。在我看来,无论是否强制转换,都必须执行 catch 块。这段代码有什么问题?
public static void main(String[] args) {
int pay=8,payda=0;
try {
double result=pay/(double)payda; // if I cast any of the two variables, program does not recognize the catch block, why is it so?
System.out.println(result);
System.out.println("inside-try");
} catch (Exception e) {
System.out.println("division by zero exception");
System.out.println("inside-catch");
}
}
回答by kennytm
Divide by zero is valid for floating point numbers.
除以零对浮点数有效。
- 1/0 yields Infinity.
- (-1)/0 yields -Infinity.
- 0/0 yields NaN.
- 1/0 产生无穷大。
- (-1)/0 产生 -Infinity。
- 0/0 产生 NaN。
These "numbers" are properly defined in IEEE 754.
这些“数字”在 IEEE 754 中有正确定义。
Integer division by zero, on the other hand, throws because one cannot represent infinity as an int
.
另一方面,整数除以零会抛出异常,因为不能将无穷大表示为int
。
回答by danben
The answer lies in your program's own output - it prints "Infinity" for result
. This is because Java only disallows integer division by zero - floating point division by zero is legal and produces Infinity
.
答案在于您的程序自己的输出 - 它为result
. 这是因为 Java 只不允许整数除以零 - 浮点除以零是合法的并产生Infinity
.
See the documentation of Doubleand Floatfor the POSITIVE_INFINITY
and NEGATIVE_INFINITY
constants.
回答by Bozho
I'd suggest verifying:
我建议验证:
if (divisor != 0) {
// calculate
}
rather than catching an exception
而不是捕捉异常
回答by Matthew Flaschen
Because dividing two doubles returns a Infinity, but doesn't throw. You can use isInfinite()to check for this. However, the appropriate solution (as already noted) is to check the denominator before the division.
因为将两个双精度相除会返回一个 Infinity,但不会抛出。您可以使用isInfinite()来检查这一点。但是,适当的解决方案(如前所述)是在除法之前检查分母。
回答by Desintegr
Only division by zero with integers will raise an ArithmeticException. Division by zero with double or float will result in Infinity.
只有用整数除以零才会引发 ArithmeticException。用 double 或 float 被零除将导致Infinity。
回答by Stephen C
Since you are a self-proclaimed "newbie", I think it would be a good idea to point out some broader issues with your code. (I know it is not production code, but just lets assume for the sake of argument that it was.)
由于您自称为“新手”,因此我认为指出您的代码的一些更广泛的问题是个好主意。(我知道这不是生产代码,但为了论证起见,让我们假设它是。)
If an exception is expected, it is usually simpler, clearer and more efficient if you detect the condition that will give rise to the exception. In this case, if you expect
divisor
to occasionally be zero it is better to test it before doing the division.On the other hand, if an exception is totally unexpected (i.e. a "bug") the best strategy is to let the exception propagate to the outermost level. At that point your application catch should catch all exceptions, log the exception stacktrace and bail out.
Apart from the previous bullet, it is a bad idea to catch
Exception
,RuntimeException
,Throwable
orError
. Doing this will catch a large number of exceptions that you probably don't intend to catch. In this case, since you are expecting anArithmeticException
, you should catch just that.It is rarely correct to use
float
ordouble
in financial applications. These types are not exact, but financial applications typically require quantities of money to be handled exactly.More generally, floating point numbers are inherently hard for lay people (and newbies) to understand. A lot of the "truths" that people expect to hold actually don't hold. For example, a floating point calculation of
1.0/3.0 + 1.0/3.0 + 1.0/3.0
does not give1.0
. Similarly (as you discovered) division by zero behaves differently. If you want to use floating point safely, you need to understand the pitfalls.
如果预期会出现异常,如果您检测到会引起异常的条件,通常会更简单、更清晰、更有效。在这种情况下,如果您希望
divisor
偶尔为零,最好在进行除法之前对其进行测试。另一方面,如果异常完全出乎意料(即“错误”),最好的策略是让异常传播到最外层。此时,您的应用程序捕获应捕获所有异常,记录异常堆栈跟踪并退出。
除了前面的项目符号之外,捕捉
Exception
、RuntimeException
、Throwable
或是个坏主意Error
。这样做将捕获大量您可能不打算捕获的异常。在这种情况下,由于您期待的是ArithmeticException
,因此您应该抓住它。使用
float
或double
在金融应用程序中很少正确。这些类型并不准确,但金融应用程序通常需要准确处理大量资金。更一般地说,浮点数本质上是外行人(和新手)难以理解的。人们期望持有的许多“真相”实际上并不成立。例如, 的浮点计算
1.0/3.0 + 1.0/3.0 + 1.0/3.0
不会给出1.0
。同样(如您所见)除以零的行为也不同。如果您想安全地使用浮点数,您需要了解其中的陷阱。
EDITelaborating the first point in response to @Jay's comment.
编辑详细阐述第一点以回应@Jay 的评论。
First, I deliberately used the word "usually". There are cases where avoiding throwing the expected exception achieves nothing.
首先,我特意用了“通常”这个词。在某些情况下,避免抛出预期的异常一事无成。
Having said that, you often don't want a generic "expected" exception to happen even if your application cannot deal with the situation immediately. For example, if the OP's code was part of something larger, it may be better to explicitly throw IllegalArgumentException
(if this is a violation of an API contract) or some checked UserEnteredRubbishException
if we know that this is a result of bad user input (and there is some opportunity to report / correct it).
话虽如此,即使您的应用程序无法立即处理这种情况,您通常也不希望发生通用的“预期”异常。例如,如果 OP 的代码是更大的东西的一部分,最好明确抛出IllegalArgumentException
(如果这违反 API 合同)或检查一些UserEnteredRubbishException
是否我们知道这是错误的用户输入的结果(并且有一些机会报告/纠正它)。
The fact that we are "expecting" an exception means by definitionthat we know more about it than (say) a generic ArithmeticException
would say. If we allow a generic exception to propagate, it makes it harder for a catch block many stack frames to act appropriately. In this case for example, the remote catch block could not diagnose the cause of the divide-by-zero with any certainty. The ArithmeticException
mighthave come from a different part of the application, and might noteven be a divide-by-zero! The way to address is to explicitly throwing a more specific exception.
我们“期待”一个异常的事实意味着,根据定义,我们对它的了解比(比如说)一个泛型ArithmeticException
会说的要多。如果我们允许一个通用的异常传播,它会使一个 catch 阻塞许多堆栈帧更难正确地采取行动。例如,在这种情况下,远程 catch 块无法确定地诊断被零除的原因。的ArithmeticException
可能都来自于应用程序的不同部分,可能不会甚至是除以零!解决方法是显式抛出更具体的异常。
回答by fastcodejava
No one should try to expect RuntimeException
to be thrown from their code. These Exception
s can be (and should be) avoided easily.
没有人应该试图期望RuntimeException
从他们的代码中抛出。这些Exception
s 可以(并且应该)轻松避免。