我从 GNU Scientific Library 得到了一个计算结果。看起来像这样
iter 0: A = 1.0000, lambda = 1.0000, b = 0.0000, cond(J) = inf, |f(x)| = 101.0200
iter 1: A = 3.5110, lambda = -12.8820, b = 1.2364, cond(J) = 92.8216, |f(x)| = -nan
iter 2: A = 3.5110, lambda = -12.8820, b = 1.2364, cond(J) = nan, |f(x)| = -nan
iter 3: A = 3.5110, lambda = -12.8820, b = 1.2364, cond(J) = nan, |f(x)| = -nan
iter 4: A = 3.5110, lambda = -12.8820, b = 1.2364, cond(J) = nan, |f(x)| = -nan
iter 5: A = 3.5110, lambda = -12.8820, b = 1.2364, cond(J) = nan, |f(x)| = -nan
iter 6: A = 3.5110, lambda = -12.8820, b = 1.2364, cond(J) = nan, |f(x)| = -nan
iter 7: A = 3.5110, lambda = -12.8820, b = 1.2364, cond(J) = nan, |f(x)| = -nan
iter 8: A = 3.5110, lambda = -12.8820, b = 1.2364, cond(J) = nan, |f(x)| = -nan
iter 9: A = 3.5110, lambda = -12.8820, b = 1.2364, cond(J) = nan, |f(x)| = -nan
iter 10: A = 3.5110, lambda = -12.8820, b = 1.2364, cond(J) = nan, |f(x)| = -nan
iter 11: A = 3.5110, lambda = -12.8820, b = 1.2364, cond(J) = nan, |f(x)| = -nan
iter 12: A = 3.5110, lambda = -12.8820, b = 1.2364, cond(J) = nan, |f(x)| = -nan
iter 13: A = 3.5110, lambda = -12.8820, b = 1.2364, cond(J) = nan, |f(x)| = -nan
iter 14: A = 3.5110, lambda = -12.8820, b = 1.2364, cond(J) = nan, |f(x)| = -nan
iter 15: A = 3.5110, lambda = -12.8820, b = 1.2364, cond(J) = nan, |f(x)| = -nan
iter 16: A = 3.5110, lambda = -12.8820, b = 1.2364, cond(J) = nan, |f(x)| = -nan
iter 17: A = 3.5110, lambda = -12.8820, b = 1.2364, cond(J) = nan, |f(x)| = -nan
iter 18: A = 3.5110, lambda = -12.8820, b = 1.2364, cond(J) = nan, |f(x)| = -nan
iter 19: A = 3.5110, lambda = -12.8820, b = 1.2364, cond(J) = nan, |f(x)| = -nan
iter 20: A = 3.5110, lambda = -12.8820, b = 1.2364, cond(J) = nan, |f(x)| = -nan
Run Code Online (Sandbox Code Playgroud)
因此,您可以cond(J) = nan, |f(x)| = -nan从第二次迭代中看到。从语言设计的角度来看,让“nan”默默地而不是中止的目的是什么?效率?
从语言设计的角度来看,让“nan”无声无息,而不是中止的目的是什么?效率?
效率是原因之一。但另一个是 C 缺乏异常的概念。考虑以下。您正在使用预编译的库,您无法访问源代码。你只有头文件和目标文件,所以你有一个double f(double arg)在头文件中声明并在目标文件中定义的函数。
那么如果你不想让程序崩溃怎么办?然后,您必须确保该函数甚至不会被调用,如果arg是一个f将返回的值NaN。这确实非常棘手。特别是在这种情况下,您甚至无法访问源代码。
在 Java 中,计算 NaN 时不会抛出异常。但如果是这样,你会做这样的事情:
try {
a = f(4.0);
} catch (NaNException) {
Run Code Online (Sandbox Code Playgroud)
你会如何在 C 中做到这一点?当涉及到整数除以零时,这实际上是 C 中的一个问题。这会在 C 中调用未定义的行为,没有机会恢复。
这个java代码:
try {
a = 100/d;
} catch (ArithmeticExpression) {
System.out.println("<d> must not be zero");
Run Code Online (Sandbox Code Playgroud)
对应于这个 C 代码:
if(d == 0) {
puts("<d> must not be zero");
} else {
a = 100/d;
Run Code Online (Sandbox Code Playgroud)
请注意,您必须在之前进行检查,这可能比之后进行检查要棘手得多。在这个简单的情况下,它是微不足道的。但是考虑一个稍微不那么琐碎的例子。假设您有一个总共执行 20 个除法的函数。那么你可能需要 20 个 if 语句来覆盖这个。我们也有上面提到的情况,在这种情况下,您无法访问源代码,而只能依靠对创建库的人的纯粹信任。
NaN 意味着所涉及的计算毫无意义或完全错误,对吗?
并不真地。代码可能完全没问题,错误可能是代码输入错误。这并不一定意味着程序需要崩溃。
C 中的错误处理基本上是由程序员来进行正确的错误检查。
实际上,您可以将其NAN用作显式错误指示器。例子:
double f(double arg) {
if(arg < 0)
return NAN;
...
}
Run Code Online (Sandbox Code Playgroud)
但要小心,因为这行不通:
if(f(a) == NAN) {
Run Code Online (Sandbox Code Playgroud)
相反,使用这个:
if(isnan(f(a))) {
Run Code Online (Sandbox Code Playgroud)