Android学生成绩排名问题:基于索引中位数的排名修正需求
学生排名中位数计算逻辑修正
需求说明
按分数降序排列学生数据,分数相同的学生以他们的索引(1-based序号)中位数作为共同排名,具体规则:
- 3个同分数学生(索引1、2、3):中位数为2 → 排名设为2.0
- 2个同分数学生(索引4、5):中位数为(4+5)÷2=4.5 → 排名设为4.5
- 5个同分数学生(索引7-11):中位数为9 → 排名设为9.0
现有代码问题
当前基于Firebase+RecyclerView的Android代码仅能正确计算前5个学生的分组排名,其余分组计算错误:
- 6个同分数学生(索引6-11):正确中位数应为8.5,实际得到8.0
- 部分2个同分数学生:正确排名应为12.5,实际得到12.0
错误原因
代码中使用整数除法计算中位数,且基于0-based的列表索引而非真实的1-based索引:
double medianIndex = (startIndex + endIndex - 1) / 2; // 整数除法会截断小数 double rank = medianIndex + 1;
例如2个学生的分组,列表索引startIndex=3、endIndex=5,整数运算(3+5-1)/2=3,加1后得到4.0,而非正确的4.5。
修正后的代码
核心修改:改用真实的1-based索引计算中位数,强制使用浮点除法保留小数:
public class ViewStudentScores extends AppCompatActivity { private DatabaseReference databaseReference; private StudentAdapter studentAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_view_student_scores); RecyclerView recyclerView = findViewById(R.id.recyclerView); recyclerView.setLayoutManager(new LinearLayoutManager(this)); studentAdapter = new StudentAdapter(); recyclerView.setAdapter(studentAdapter); databaseReference = FirebaseDatabase.getInstance().getReference("students"); databaseReference.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot dataSnapshot) { List<Student> students = new ArrayList<>(); for (DataSnapshot snapshot : dataSnapshot.getChildren()) { Student student = snapshot.getValue(Student.class); students.add(student); } // 按分数降序排序 Collections.sort(students, new Comparator<Student>() { @Override public int compare(Student student1, Student student2) { return Double.compare(student2.getScore(), student1.getScore()); } }); // 为同分数学生分配基于索引中位数的排名 int totalStudents = students.size(); int startIndex = 0; while (startIndex < totalStudents) { int endIndex = startIndex + 1; // 找到当前分数分组的结束位置 while (endIndex < totalStudents && students.get(startIndex).getScore() == students.get(endIndex).getScore()) { endIndex++; } // 计算当前分组的真实1-based索引范围 int firstRealIndex = startIndex + 1; int lastRealIndex = endIndex; // 因为endIndex是下一组的起始,当前组最后一个的真实索引是endIndex // 计算中位数排名(浮点除法保留小数) double medianRank = (firstRealIndex + lastRealIndex) / 2.0; // 为当前分组的所有学生设置排名 for (int i = startIndex; i < endIndex; i++) { students.get(i).setRank(medianRank); } startIndex = endIndex; } // 更新RecyclerView数据 studentAdapter.setStudents(students); } @Override public void onCancelled(@NonNull DatabaseError error) { // 处理数据库错误 } }); }
验证说明
- 6个同分数学生(索引6-11):
(6+11)/2.0=8.5,符合预期 - 2个同分数学生(索引12、13):
(12+13)/2.0=12.5,符合预期 - 奇数个分组(如3个、5个):计算结果与需求完全匹配
内容的提问来源于stack exchange,提问作者F.joel
相关产品推荐
相关产品推荐

