当我使用 switch 语句运行我的程序(使用 gcc -std=c99 -lm)时,此行中计算的所有“因素”:
factors[rows][0]=cbrtf((3+(float)scores[rows][1])/(3+(float)scores[rows][3]));
被报告为“NaN”。如果我注释掉 switch 语句,同一行将完美运行。谁能解释一下?
作为一个单独的问题,其他开关案例:
factors[rows][0]=((float)scores[rows][1])/(((float)scores[rows][1])+((float)scores[rows][3]));
和
factors[rows][0]=log((((float)scores[rows][1])/(((float)scores[rows][1])+((float)scores[rows][3] )))+1);
导致 NaN,无论是在开关内部还是外部。我已经检查了我的 paretheses 十几次。不可能被零除(因为分母中的分数之和必须为正),并且为了防止取零的自然对数,这是未定义的,我将 1 添加到始终介于 0 和 1 之间的商包括的。为什么这些线会产生 NaN?
这是自 1973 年 Fortran IV 简介以来我编写的第一个程序,因此它可能是显而易见的。 . .
这是一大块代码:
//int iPreference=0;
//printf("\n1\tCube root of (Points scored by Team A + 3)/(Points scored by Team B + 3)\n");
//printf("2\tFraction of game points scored by Team A\n");
//printf("3\tln of [(percentage of game points scored by Team A) + 1]\n");
//printf("\nPlease select your preference (1-3): ");
//scanf("%d", &iPreference);
for (rows=0; rows<games; rows++)
{
scores[rows][0]=values[rows].iA_ID;
scores[rows+games][0]=values[rows].iB_ID;
scores[rows][1]=values[rows].iA_Points;
scores[rows+games][1]=values[rows].iB_Points;
scores[rows][2]=values[rows].iB_ID;
scores[rows+games][2]=values[rows].iA_ID;
scores[rows][3]=values[rows].iB_Points;
scores[rows+games][3]=values[rows].iA_Points;
scores[rows][4]=0; // Column 4 will be checked off with a '1' once a game has been evaluated
scores[rows+games][4]=0;
factors[rows][1]=1; // Seed every team with a starting value of 1
factors[rows+games][1]=1;
//switch (iPreference)
//{
// case 1:
factors[rows][0]=cbrtf((3+(float)scores[rows][1])/(3+(float)scores[rows][3]));
factors[rows+games][0]=cbrtf((3+(float)scores[rows+games][1])/(3+(float)scores[rows+games][3]));
// case 2:
// factors[rows][0]=((float)scores[rows][1])/(((float)scores[rows][1])+((float)scores[rows][3]));
// factors[rows+games][0]=((float)scores[rows+games][1])/(((float)scores[rows+games][1])+((float)scores[rows+games][3]));
// case 3:
// factors[rows][0]=log((((float)scores[rows][1])/(((float)scores[rows][1])+((float)scores[rows][3])))+1);
// factors[rows+games][0]=log((((float)scores[rows+games][1])/(((float)scores[rows+games][1])+((float)scores[rows+games][3])))+1);
//}
}
随着立方根变小,它们可能会达到范围为 [3.410^-38, 3.410^38] 的浮点数的极限,在这种情况下,您需要使用 double 和
cbrt()
将增加范围并避免除以零。
添加打印语句以了解 NaN 发生的原因/时间可能会很好:
// add this at the top if you don't already have it
#include <stdio.h>
/* place this somewhere before the case statement */
float custom_NAN = 0.0/0.0;
/* place this somewhere after you set factors[rows][0]
to stop the program when you hit a NaN. Remove
exit(0) if you want this to continue after computing a NaN
*/
if ( factors[rows][0] == custom_NAN ) {
// print the numerator and denominator
printf("\tNumerator:(%E) / Denominator(%E) = %E\n", (float)scores[rows][1], ((float)scores[rows][1]+(float)scores[rows][3]), (float)scores[rows][0]);
// end the program and review
exit(0);
}