输出是 -1.#QNAN0,我不知道为什么

时间:2021-05-08 04:21:41

标签: c floating-point

#include <stdio.h>
#include <math.h>

int main(void) {
  double stotal, smean, sd, ermean, total, mean, j, k;
  int n, i;

  printf("enter n numbers to be entered\n");
  scanf(" %d", &n);

  double x[n];

  for (i = 0; i < n; i++) {
    printf("enter value for X\n");
    scanf(" %lf", &x[i]);
  }

  for (i = 0; i < n; i++) {
    j = x[i];
    stotal = stotal + (j * j);
    printf("%f\n", total);
  }
  for (i = 0; i < n; i++) {
    k = x[i];
    total = total + k;
    printf("%f\n", total);
  }

  mean = total / n;
  smean = stotal / n;
  sd = sqrt(smean - pow(mean, 2));
  ermean = sd / sqrt(n);
  printf("sum is                    %lf\n", total);
  printf("mean is                   %lf\n", mean);
  printf("sum squared is            %lf\n", stotal);
  printf("mean squared is           %lf\n", smean);
  printf("standard deviation is     %lf\n", sd);
  printf("error in mean is          %lf", ermean);
  return 0;
}

输出:

sum is -1.#QNAN0
mean is -1.#QNAN0

总和和均值的输出关闭,我怀疑是我的整个功能有问题,但我不知道如何修复它。

编辑:
这次重新编辑了代码并进行了初始化,抱歉给出了一个令人困惑的声明,该代码实际上适用于一个非常大的值,我只是忘记完全初始化必要的变量。

编辑代码:

double stotal=0,smean=0,sd=0,total=0,mean=0,j,k;

1 个答案:

答案 0 :(得分:1)

total, stotal 未初始化。


“输入一个非常大的值” --> 对于大 x[i]stotal 可能由于 stotal + (j * j) 而变得无穷大。然后是在 smean - pow(mean, 2) 中减去无穷大的问题。


<块引用>

输出是-1.#QNAN0,我不知道为什么

注意真实数学和浮点数学之间的细微差别。

考虑到 smean - pow(mean, 2) 可能由于 FP 数学的四舍五入而略微为负,即使在数学上这不是预期的。

sd = sqrt(smean - pow(mean, 2));  // What if smean < pow(mean, 2) ?

当然 sqrt(some_negative) 会导致诸如 -1.#QNAN0 之类的麻烦。

相反,要防范1

// sd = sqrt(smean - pow(mean, 2));
double diff = smean - pow(mean, 2);
sd = diff < 0.0 ? 0.0 : sqrt(diff);

高级:可以在下面使用以应对 -0.0。 -0.0 通常适用于 sqrt(-0.0) --> -0.0。不过,最好避免 -0.0 标准偏差。

sd = signbit(diff) ? 0.0 : sqrt(diff);

类似问题acosf() returns NaN


提示:不要使用 "%lf" 打印,而是使用 "%lg"(或仅使用 "%g")——尤其是在调试 FP 代码时。小值信息更丰富,大值噪声更少。


1 使用此代码,任何负 diff 肯定是由于累积计算和舍入效果,标准偏差确实为 0.0。这里 diff < 0.0 是合理的。

注意这种泛化这个测试,尽管 sqrt() 的扩充比通过舍入误差合理化的结果要消极得多,以避免 < 0.0 测试隐藏一些更大的缺陷。