Hướng dẫn giải của Máy tính bỏ túi đơn giản
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Lời giải này đang bị ẩn cho đến khi bạn chọn mở ra.
Chúng tôi khuyên bạn nên tự thử giải bài trước. Việc mở lời giải có thể làm lộ mất ý tưởng chính trước khi bạn có cơ hội tự giải.
Bạn phải đăng nhập để mở lời giải này.
Đăng nhậpTác giả: , , ,
Hiểu bài toán
Bài toán yêu cầu viết một chương trình mô phỏng máy tính bỏ túi đơn giản với 4 phép toán cơ bản: cộng (+), trừ (-), nhân (*) và chia (/). Đầu vào gồm hai số thực và một toán tử ở giữa. Đầu ra là kết quả của phép toán được làm tròn đến 2 chữ số thập phân. Trường hợp đặc biệt, nếu phép chia cho 0 (b = 0), chương trình phải in ra thông báo 'Math Error'.
Các cách tiếp cận
Cách Sử dụng cấu trúc rẽ nhánh if-else
#include <stdio.h>
#include <stdlib.h>
int main() {
double a, b;
char c;
scanf("%lf %c %lf", &a, &c, &b);
if (c == '+') printf("%.2lf", a + b);
else if (c == '-') printf("%.2lf", a - b);
else if (c == '*') printf("%.2lf", a * b);
else if (c == '/') {
if (b == 0) printf("Math Error");
else printf("%.2lf", a / b);
}
return 0;
}
- Time Complexity: O(1)
- Space Complexity: O(1)
Đây là cách tiếp cận trực quan và phổ biến nhất. Chương trình đọc vào hai số thực và một ký tự toán tử. Sử dụng chuỗi lệnh if-else if để kiểm tra từng trường hợp toán tử (+, -, *, /). Với mỗi trường hợp, thực hiện phép tính tương ứng và in kết quả. Riêng với phép chia, ta cần kiểm tra thêm điều kiện b != 0 trước khi thực hiện chia để tránh lỗi runtime. Nếu b bằng 0, in ra 'Math Error'.
Cách Sử dụng cấu trúc rẽ nhánh if độc lập
#include <stdio.h>
#include <stdlib.h>
int main() {
double a, b;
char c;
scanf("%lf %c %lf", &a, &c, &b);
if (c == '+') printf("%.2lf", a + b);
if (c == '-') printf("%.2lf", a - b);
if (c == '*') printf("%.2lf", a * b);
if (c == '/') {
if (b == 0) printf("Math Error");
else printf("%.2lf", a / b);
}
// Trường hợp lỗi cú pháp (toán tử không hợp lệ) không được xử lý trong code này,
// nhưng theo đề bài luôn đảm bảo toán tử hợp lệ.
return 0;
}
- Time Complexity: O(1)
- Space Complexity: O(1)
Khác với cách trên, phương pháp này sử dụng các câu lệnh if độc lập cho mỗi toán tử. Mặc dù về mặt logic, chỉ có một toán tử hợp lệ nên kết quả tính toán sẽ chỉ in ra một lần, nhưng về hiệu năng, CPU vẫn phải thực hiện kiểm tra tất cả các điều kiện (4 lần kiểm tra) thay vì dừng lại sau khi tìm thấy điều kiện đúng (như trong else if). Tuy nhiên, với bài toán nhỏ này thì sự chênh lệch không đáng kể.
Cách Tối ưu hóa logic xử lý chia
#include <stdio.h>
#include <stdlib.h>
int main() {
double a, b;
char c;
scanf("%lf %c %lf", &a, &c, &b);
if (c == '+') printf("%.2lf", a + b);
else if (c == '-') printf("%.2lf", a - b);
else if (c == '*') printf("%.2lf", a * b);
else {
// Toán tử duy nhất còn lại là '/'
if (b != 0) printf("%.2lf", a / b);
else printf("Math Error");
}
return 0;
}
- Time Complexity: O(1)
- Space Complexity: O(1)
Đây là biến thể của cách tiếp cận đầu tiên, tối ưu hóa một chút về mặt cấu trúc. Thay vì kiểm tra if (c == '/'), ta có thể dùng else cuối cùng vì đề bài đảm bảo toán tử nhập vào luôn là 1 trong 4 ký tự cho trước. Nếu đã đi đến else (tức không phải +, -, *), thì chắc chắn đó là phép chia. Cách này có thể giảm nhẹ số lần so sánh chuỗi if-else.
Phân tích độ phức tạp
| Cách tiếp cận | Time | Space | Tên |
|---|---|---|---|
| 1 | O(1) | O(1) | Sử dụng cấu trúc rẽ nhánh if-else |
| 2 | O(1) | O(1) | Sử dụng cấu trúc rẽ nhánh if độc lập |
| 3 | O(1) | O(1) | Tối ưu hóa logic xử lý chia |
Bài học kinh nghiệm
- Đầu vào luôn hợp lệ nên không cần kiểm tra lỗi cú pháp (toán tử không đúng quy định).
- Phép chia là trường hợp duy nhất cần xử lý lỗi (chia cho 0).
- Sử dụng format specifier
%.2lf(hoặc%.2f) trong hàmprintflà cách đơn giản nhất để làm tròn và định dạng đầu ra theo yêu cầu.
Lỗi thường gặp
- Lỗi 'Division by Zero': Quên kiểm tra biến
bcó bằng 0 trước khi thực hiện phép chia, dẫn đến chương trình bị crash hoặc kết quả không xác định (Infinity/NaN). - Sai loại dữ liệu: Sử dụng
floatthay vìdoublecó thể dẫn đến sai số làm tròn nếu yêu cầu độ chính xác cao (mặc dù với giới hạn 10000 và làm tròn 2 chữ số thập phân thìfloatthường đủ, nhưngdoublelà chuẩn an toàn hơn). - Lỗi định dạng nhập xuất: Sai format string trong
scanf(ví dụ: thiếu khoảng trắng giữa%lfvà%c) có thể khiến việc đọc dữ liệu bị sai lệch.
Bình luận