【问题标题】:Output is -1.#QNAN0 and I don't know why [closed]输出为-1.#QNAN0,我不知道为什么[关闭]
【发布时间】:2021-05-08 04:21:41
【问题描述】:
#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

sum & mean 的输出关闭,我怀疑它的总功能有问题,但我不知道如何修复它。

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

修改后的代码:

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

【问题讨论】:

  • total 未初始化,如果您打开编译器警告就会发现。
  • stotal 也未初始化。
  • 啊,忘了。
  • 还有一个问题,但是输入一个非常大的值仍然会导致同样的问题。 sd & ermean 输出为-1#IND00
  • @anno:编辑问题以提供minimal reproducible example,包括重现问题的“非常大的值”。

标签: c floating-point


【解决方案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 &lt; 0.0是合理的。

请注意这种泛化此测试,尽管对sqrt() 的扩充远比通过舍入错误来合理化以避免&lt; 0.0 测试隐藏一些更大的缺陷更消极。

【讨论】:

猜你喜欢
  • 2014-06-25
  • 2013-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多