两均值t检验C语言代码输出inf值的问题排查求助
两样本t检验C代码输出inf问题排查与修复
问题描述
编写了用于检验两均值差异的t检验C语言代码,运行后t值输出为inf,已初始化所有变量但无法定位问题。使用的样本数据:
- 样本1(容量6):63、65、68、69、71、72
- 样本2(容量10):61、62、65、66、69、69、70、71、72、73
原始代码
#include <stdio.h> #include <math.h> float mean(float x[], int size) { float sum = 0.0; for (int i=0; i<size;i++) sum += x[i]; return sum/size; } float sumsq(float x[], int size) { float sum = 0.0; for (int i=0; i<size;i++) sum += pow(x[i]-mean(x,size),2); return sum; } int main(void) { int n,m; // sample sizes float x=0.0,y=0.0,s1=0.0,s2=0.0,S=0.0,t=0.0,tcal; printf("Enter the sample sizes of the first and second samples\n"); scanf("%d %d",&n,&m); float a[n],b[m]; printf("Enter the values of 1st sample\n"); for(int i=0;i<n;i++) scanf("%f", &a[i]); printf("Enter the values of 2nd sample\n"); for(int i=0;i<m;i++) scanf("%f", &b[i]); x = mean(a,n); y = mean(b,m); s1 = sumsq(a, n); s2 = sumsq(b, m); S = sqrt((s1+s2)/(n+m-2)); t = (x-y)/(S*sqrt(1/n+1/m)); printf("Enter the value of t for ur desired level of significance for %d degrees of freedom\n", m+n-2); scanf("%f", &tcal); printf("%f\n", x); printf("%f\n", y); printf("%f\n", s1); printf("%f\n", s2); printf("%f\n", S); printf("%f\n", t); if (t < tcal) printf("There is not enough evidence to reject null hypothesis, so, both means can be considered equal\n"); else printf("Both means have a siginificant difference\n"); return 0; }
问题根源
- 整数除法导致分母为0:计算
sqrt(1/n+1/m)时,n和m是整数类型,1/n和1/m会触发整数除法,结果均为0,最终1/n+1/m=0,开平方后仍为0。此时t = (x-y)/(S*0),当S不为0时,结果就会是inf。 - sumsq函数效率低下:每次循环都重复调用
mean函数,时间复杂度为O(n²),虽不直接导致inf,但严重影响性能。 - pow函数精度与效率问题:使用
pow计算平方,不如直接用乘法(x[i]-mu)*(x[i]-mu)高效且精度更稳定。
修复后的代码
#include <stdio.h> #include <math.h> // 计算均值 float mean(float x[], int size) { float sum = 0.0; for (int i = 0; i < size; i++) sum += x[i]; return sum / size; } // 计算离均差平方和:先算一次均值,避免重复计算 float sumsq(float x[], int size) { float mu = mean(x, size); float sum = 0.0; for (int i = 0; i < size; i++) { float diff = x[i] - mu; sum += diff * diff; // 替换pow,提升效率和精度 } return sum; } int main(void) { int n, m; float x_mean = 0.0, y_mean = 0.0, s1 = 0.0, s2 = 0.0, S = 0.0, t = 0.0, tcal; printf("Enter the sample sizes of the first and second samples\n"); scanf("%d %d", &n, &m); float a[n], b[m]; printf("Enter the values of 1st sample\n"); for(int i = 0; i < n; i++) scanf("%f", &a[i]); printf("Enter the values of 2nd sample\n"); for(int i = 0; i < m; i++) scanf("%f", &b[i]); x_mean = mean(a, n); y_mean = mean(b, m); s1 = sumsq(a, n); s2 = sumsq(b, m); // 合并方差计算 S = sqrt((s1 + s2) / (n + m - 2)); // 用1.0强制浮点除法,避免整数除法为0 t = (x_mean - y_mean) / (S * sqrt(1.0/n + 1.0/m)); printf("Enter the critical t-value for your desired significance level (%d degrees of freedom):\n", n + m - 2); scanf("%f", &tcal); // 输出中间结果 printf("Sample 1 mean: %.2f\n", x_mean); printf("Sample 2 mean: %.2f\n", y_mean); printf("Sum of squares (sample 1): %.2f\n", s1); printf("Sum of squares (sample 2): %.2f\n", s2); printf("Pooled standard deviation: %.2f\n", S); printf("Calculated t-value: %.4f\n", t); // 假设检验判断(双侧检验用绝对值比较更严谨) if (fabs(t) < tcal) printf("Fail to reject the null hypothesis: the means are not significantly different.\n"); else printf("Reject the null hypothesis: the means are significantly different.\n"); return 0; }
修复说明
- 把
1/n改为1.0/n,1/m改为1.0/m,强制触发浮点除法,避免分母为0的情况。 - 优化
sumsq函数:先计算一次均值再循环,将时间复杂度降为O(n)。 - 用
diff*diff替换pow(diff, 2),提升计算效率与精度。 - 补充了绝对值判断(双侧检验的常规逻辑),修正了原判断的疏漏。
- 优化了输出格式,让结果更易读。
内容的提问来源于stack exchange,提问作者Anweshan Goswami
相关产品推荐
相关产品推荐

