code rút gọn phân số bằng C++
Chúng ta sẽ cùng nhau tìm hiểu cách giải bài toán này một cách chi tiết, bám sát kiến thức đã học trong Sách giáo khoa Tin học lớp 8, và tuyệt đối không đi quá giới hạn kiến thức của chương trình.
Bước 1: Hiểu rõ bài toán rút gọn phân số
Phân số được biểu diễn dưới dạng \(\frac{a}{b}\), trong đó \(a\) là tử số và \(b\) là mẫu số. Rút gọn phân số có nghĩa là tìm một phân số tương đương với phân số ban đầu nhưng có tử số và mẫu số nhỏ hơn. Ví dụ, phân số \(\frac{6}{9}\) có thể rút gọn thành \(\frac{2}{3}\).
Làm thế nào để rút gọn? Chúng ta cần tìm một số nguyên \(d\) sao cho cả tử số \(a\) và mẫu số \(b\) đều chia hết cho \(d\). Số \(d\) này chính là ước chung của \(a\) và \(b\). Để phân số được rút gọn nhất có thể, chúng ta cần chia cả tử số và mẫu số cho ước chung lớn nhất (ƯCLN) của chúng.
Bước 2: Tìm hiểu về Ước chung lớn nhất (ƯCLN)
Ước chung lớn nhất của hai hay nhiều số nguyên là số nguyên dương lớn nhất, mà tất cả các số đó đều chia hết. Ví dụ:
* ƯCLN(12, 18) = 6
* ƯCLN(24, 36) = 12
Trong lập trình, chúng ta có thuật toán rất hiệu quả để tìm ƯCLN, đó là thuật toán Euclid.
Bước 3: Áp dụng thuật toán Euclid để tìm ƯCLN trong C++
Thuật toán Euclid dựa trên nguyên tắc:
Nếu \(b = 0\) thì ƯCLN(a, b) = a.
Ngược lại, ƯCLN(a, b) = ƯCLN(b, a \pmod{b}).
Ở đây, \(a \pmod{b}\) là phép chia lấy dư của \(a\) cho \(b\).
Chúng ta có thể cài đặt thuật toán này dưới dạng một hàm trong C++ để tái sử dụng.
cpp
// Hàm tìm ƯCLN bằng thuật toán Euclid
int tim_ucln(int a, int b) {
// Nếu b bằng 0, thì a chính là ƯCLN
if (b == 0) {
return a;
}
// Nếu b khác 0, gọi đệ quy với b và phần dư của a chia cho b
return tim_ucln(b, a % b);
}
Giải thích chi tiết về hàm \(tim_ucln\):
* \(int tim_ucln(int a, int b)\): Đây là khai báo của hàm. Hàm có tên là \(tim_ucln\), nhận hai tham số đầu vào là hai số nguyên \(a\) và \(b\), và sẽ trả về một giá trị nguyên (là ƯCLN của \(a\) và \(b\)).
* \(if (b == 0)\): Đây là điều kiện dừng của thuật toán. Khi số thứ hai (\(b\)) trở thành 0, thì số thứ nhất (\(a\)) chính là ƯCLN.
* \(return a;\): Trả về giá trị của \(a\).
* \(return tim_ucln(b, a % b);\): Đây là bước đệ quy. Hàm gọi lại chính nó nhưng với tham số mới là \(b\) và kết quả của phép chia lấy dư \(a % b\). Quá trình này lặp đi lặp lại cho đến khi điều kiện \(b == 0\) được thỏa mãn.
Lưu ý: Thuật toán Euclid hoạt động tốt với các số không âm. Nếu chúng ta gặp phân số có số âm, chúng ta có thể xử lý bằng cách lấy giá trị tuyệt đối của tử và mẫu khi tìm ƯCLN. Tuy nhiên, trong phạm vi bài học này, chúng ta sẽ giả định tử và mẫu là các số nguyên dương để đơn giản hóa.
Bước 4: Xây dựng chương trình C++ để rút gọn phân số
Bây giờ, chúng ta sẽ kết hợp hàm tìm ƯCLN với logic rút gọn phân số.
cpp
#include
// Hàm tìm ƯCLN bằng thuật toán Euclid
int tim_ucln(int a, int b) {
if (b == 0) {
return a;
}
return tim_ucln(b, a % b);
}
int main() {
int tu_so, mau_so;
// Nhập tử số và mẫu số từ bàn phím
std::cout << "Nhap tu so: ";
std::cin >> tu_so;
std::cout << "Nhap mau so: "; std::cin >> mau_so;
// Kiểm tra mẫu số có bằng 0 không để tránh lỗi chia cho 0
if (mau_so == 0) {
std::cout << "Mau so khong duoc bang 0." << std::endl;
return 1; // Kết thúc chương trình với mã lỗi
}
// Tìm ƯCLN của tử số và mẫu số
// Sử dụng giá trị tuyệt đối để đảm bảo ƯCLN luôn dương
int ucln = tim_ucln(std::abs(tu_so), std::abs(mau_so));
// Rút gọn phân số bằng cách chia cả tử và mẫu cho ƯCLN
int tu_so_rut_gon = tu_so / ucln;
int mau_so_rut_gon = mau_so / ucln;
// Hiển thị phân số đã rút gọn
std::cout << "Phan so sau khi rut gon la: " << tu_so_rut_gon << "/" << mau_so_rut_gon << std::endl;
return 0; // Kết thúc chương trình thành công
}
Giải thích chi tiết chương trình:
* \(#include
* \(int tim_ucln(int a, int b) { … }\): Đây là hàm tìm ƯCLN mà chúng ta đã phân tích ở Bước 3.
* \(int main() { … }\): Đây là hàm chính, nơi chương trình bắt đầu thực thi.
* \(int tu_so, mau_so;\): Khai báo hai biến nguyên để lưu trữ tử số và mẫu số của phân số.
* \(std::cout << "Nhap tu so: ";\) và \(std::cin >> tu_so;\): Yêu cầu người dùng nhập tử số và lưu vào biến \(tu_so\).
* \(std::cout << "Nhap mau so: ";\) và \(std::cin >> mau_so;\): Yêu cầu người dùng nhập mẫu số và lưu vào biến \(mau_so\).
* \(if (mau_so == 0) { … }\): Đây là một kiểm tra an toàn quan trọng. Nếu mẫu số người dùng nhập là 0, chương trình sẽ thông báo lỗi và dừng lại để tránh gây ra lỗi chương trình.
* \(int ucln = tim_ucln(std::abs(tu_so), std::abs(mau_so));\):
* \(std::abs(tu_so)\) và \(std::abs(mau_so)\): Chúng ta sử dụng hàm \(abs()\) (cần bao gồm \(
* \(int ucln = …;\): Gọi hàm \(tim_ucln\) với giá trị tuyệt đối của tử và mẫu, và lưu kết quả vào biến \(ucln\).
* \(int tu_so_rut_gon = tu_so / ucln;\): Chia tử số ban đầu cho ƯCLN để có tử số mới đã rút gọn.
* \(int mau_so_rut_gon = mau_so / ucln;\): Chia mẫu số ban đầu cho ƯCLN để có mẫu số mới đã rút gọn.
* \(std::cout << "Phan so sau khi rut gon la: " << tu_so_rut_gon << "/" << mau_so_rut_gon << std::endl;\): In ra kết quả phân số đã được rút gọn.
* \(return 0;\): Báo hiệu rằng chương trình đã kết thúc thành công.
Ví dụ minh họa:
Nếu em nhập tử số là 12 và mẫu số là 18:
1. Chương trình sẽ gọi \(tim_ucln(abs(12), abs(18))\), tức là \(tim_ucln(12, 18)\).
2. \(tim_ucln(12, 18)\) gọi \(tim_ucln(18, 12 % 18)\), tức là \(tim_ucln(18, 12)\).
3. \(tim_ucln(18, 12)\) gọi \(tim_ucln(12, 18 % 12)\), tức là \(tim_ucln(12, 6)\).
4. \(tim_ucln(12, 6)\) gọi \(tim_ucln(6, 12 % 6)\), tức là \(tim_ucln(6, 0)\).
5. \(tim_ucln(6, 0)\) trả về \(6\). Vậy \(ucln\) là \(6\).
6. Tử số rút gọn = \(12 / 6 = 2\).
7. Mẫu số rút gọn = \(18 / 6 = 3\).
8. Kết quả hiển thị: \(Phan so sau khi rut gon la: 2/3\).
Kết luận:
Các em thấy đó, việc rút gọn phân số trong C++ trở nên đơn giản khi chúng ta biết cách tìm ƯCLN bằng thuật toán Euclid. Bài tập này đã giúp chúng ta ôn lại kiến thức về hàm, cấu trúc điều khiển \(if\), phép toán modulo (\(%\)), và đặc biệt là áp dụng một thuật toán toán học quen thuộc vào lập trình.
Hãy tự mình thử nghiệm chương trình này với nhiều cặp tử số và mẫu số khác nhau nhé. Nếu có bất kỳ câu hỏi nào, đừng ngần ngại hỏi thầy. Chúc các em học tốt!
\(Code\) \(C\)++:
#include <bits/stdc++.h>
using namespace std;
int gcd(int a, int b){
if (b == 0)
return a;
return gcd(b, a % b);
}
int main(){
int a, b ;
cin >> a >> b;
if (b == 0){
cout << “INVALID”;
}
else
if (a == 0){
cout <<“0”;
}
else{
if (b/gcd(b, a % b) == 1){
cout << a/gcd(b, a % b);
}
else {
if (a/gcd(b, a % b) > 0 && b/gcd(b, a % b) < 0){
cout << (-a)/gcd(b, a % b) << ” ” << (-b)/gcd(b, a % b);
}
else
cout << a/gcd(b, a % b) << ” ” << b/gcd(b, a % b);
}
}
}
________________________________
\(@\)\(kieu\)
Giải thích các bước giải:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll UCLN(ll a, ll b)
{
if (b == 0)
return a;
return UCLN(b, a % b);
}
int main()
{
ll a, b ;
cin >> a >> b;
if (b == 0)
{
cout << “INVALID”;
}
else if (a == 0)
{
cout <<“0”;
}
else
{
if (b/UCLN(b, a % b) == 1)
{
cout << a/UCLN(b, a % b);
}
else
{
if (a/UCLN(b, a % b) > 0 && b/UCLN(b, a % b) < 0)
{
cout << (-a)/UCLN(b, a % b) << ” ” << (-b)/UCLN(b, a % b);
}
else
cout << a/UCLN(b, a % b) << ” ” << b/UCLN(b, a % b);
}
}
}