Toán tử chia số nguyên
Vấn đề
Phần tiêu đề “Vấn đề”Phép chia (/) giữa hai số nguyên trong Java luôn cho ra kết quả nguyên - phần thập phân bị cắt bỏ hoàn toàn, không được làm tròn:
int a = 7;int b = 2;System.out.println(a / b); // 3 - KHÔNG phải 3.5!
System.out.println(5 / 2); // 2System.out.println(-5 / 2); // -2 (cắt về phía 0, không phải làm tròn xuống -3)System.out.println(1 / 3); // 0Vì sao nguy hiểm?
Phần tiêu đề “Vì sao nguy hiểm?”Rất dễ bất ngờ khi tính toán trung bình, tỷ lệ phần trăm, hoặc bất kỳ phép chia nào mong đợi kết quả thập phân, nhưng cả hai toán hạng đều là số nguyên:
int totalScore = 85;int numberOfStudents = 3;
double average = totalScore / numberOfStudents; // NGUY HIỂM!System.out.println(average); // 28.0 - SAI! (85/3 thực chất là 28.333...)Ở đây, totalScore / numberOfStudents được tính bằng phép chia số nguyên (85 / 3 = 28) trước, rồi kết quả 28 mới được ép kiểu ngầm sang double (28.0) khi gán cho average - phần thập phân đã mất từ bước tính toán, không thể lấy lại được nữa.
Giải pháp
Phần tiêu đề “Giải pháp”Ép kiểu ít nhất một trong hai toán hạng sang double trước khi chia:
double average = (double) totalScore / numberOfStudents; // ép totalScore sang double TRƯỚCSystem.out.println(average); // 28.333333333333332 - ĐÚNG!// Các cách viết tương đương khác:double average2 = totalScore / (double) numberOfStudents;double average3 = (double) totalScore / (double) numberOfStudents;⚠️ Ép kiểu sau khi đã chia xong ((double) (totalScore / numberOfStudents)) không giải quyết được vấn đề - phép chia số nguyên đã xảy ra và mất dữ liệu trước khi ép kiểu.
Với phép chia lấy dư %
Phần tiêu đề “Với phép chia lấy dư %”Toán tử % cũng tuân theo quy tắc tương tự - dấu của kết quả theo dấu của số bị chia (toán hạng bên trái):
System.out.println(7 % 3); // 1System.out.println(-7 % 3); // -1 (không phải 2)System.out.println(7 % -3); // 1 (không phải -2)Tóm tắt
Phần tiêu đề “Tóm tắt”Chia hai số nguyên trong Java luôn ra kết quả nguyên - phần thập phân bị cắt bỏ, không làm tròn.
- Ép kiểu một trong hai toán hạng sang
doubletrước khi chia, không phải sau khi đã chia xong%lấy dấu theo số bị chia (toán hạng bên trái), không phải theo quy tắc toán học “modulo” thông thường