如何修复代码中的无限循环?GPA统计结果异常排查
问题:二分查找出现无限循环且计数异常
编写的Java代码在处理数据集{1.14,1.49,1.54,1.86,2.04,2.19,2.86,3.02,3.16}时,出现无限循环,变量ogrenciSayisi(学生数量)持续递增,预期输出应为1,但无法定位问题。代码如下:
public class Main { public static void main(String[] args) { int ogrenciSayisi=0; if (Student.readCSV("siraliogrenci.txt").length!=0) { Student[] student = Student.readCSV("siraliogrenci.txt"); int alt_indis=0; int ust_indis=student.length-1; int orta_indis; while(alt_indis<=ust_indis){ orta_indis=(alt_indis+ust_indis)/2; if (student[orta_indis].getGPA()==3.02) { ogrenciSayisi++; int solIndis = orta_indis-1; int sagIndis = orta_indis+1; while (solIndis>=0 && student[solIndis].getGPA()==3.02) { ogrenciSayisi++; solIndis--; } while (sagIndis<student.length && student[sagIndis].getGPA()==3.02) { ogrenciSayisi++; sagIndis++; } } else if(student[orta_indis].getGPA()<3.02){ alt_indis=orta_indis+1; } else{ ust_indis=orta_indis-1; } } } System.out.println(ogrenciSayisi); } }
问题分析
- 无限循环根源:找到目标GPA并完成左右统计后,外层的
while(alt_indis<=ust_indis)循环没有终止逻辑,会重复执行二分查找,导致循环无法结束,同时ogrenciSayisi被反复累加。 - 浮点数比较精度问题:直接用
==比较浮点数(getGPA()==3.02)存在风险,浮点数在计算机中存储时可能有微小精度误差,会导致本该匹配的目标无法识别,或出现意外匹配。
修复后的代码
public class Main { public static void main(String[] args) { int ogrenciSayisi=0; Student[] students = Student.readCSV("siraliogrenci.txt"); if (students.length != 0) { int alt_indis = 0; int ust_indis = students.length - 1; int orta_indis; // 定义浮点数比较的精度阈值 final double EPSILON = 1e-6; while (alt_indis <= ust_indis) { orta_indis = (alt_indis + ust_indis) / 2; double currentGPA = students[orta_indis].getGPA(); // 通过精度阈值判断浮点数是否相等 if (Math.abs(currentGPA - 3.02) < EPSILON) { ogrenciSayisi++; int solIndis = orta_indis - 1; int sagIndis = orta_indis + 1; // 统计左侧相同GPA的学生 while (solIndis >= 0 && Math.abs(students[solIndis].getGPA() - 3.02) < EPSILON) { ogrenciSayisi++; solIndis--; } // 统计右侧相同GPA的学生 while (sagIndis < students.length && Math.abs(students[sagIndis].getGPA() - 3.02) < EPSILON) { ogrenciSayisi++; sagIndis++; } // 完成统计后终止外层循环 break; } else if (currentGPA < 3.02) { alt_indis = orta_indis + 1; } else { ust_indis = orta_indis - 1; } } } System.out.println(ogrenciSayisi); } }
关键修改点
- 找到目标并完成统计后,添加
break终止外层二分查找循环,避免无限循环和重复计数。 - 替换浮点数直接比较逻辑,用
Math.abs(currentGPA - 3.02) < EPSILON判断相等,规避精度问题。 - 优化变量命名(
student改为students),提升代码可读性。
内容的提问来源于stack exchange,提问作者özkan
相关产品推荐
相关产品推荐

