Lab 01 — Môi trường, mảng, vòng lặp
LAB 01 — GIẢI CHI TIẾT (MÔI TRƯỜNG, MẢNG, VÒNG LẶP)
Nguồn:
JavaLabStart_.pdf. Bám theo lý thuyết buổi 1, 2, 4, 7 trongbai-giang-java. Cách dùng: đọc mục 0–4 của từng bài, tự viết, rồi so với mục 5. Đừng đọc mục 5 trước.
Phần A — Cài đặt môi trường (mục 2.1, 2.2 của đề)
Đây là bài không có code, nhưng là bài chấm điểm đầu
tiên: nếu javac không chạy, mọi bài sau bằng 0.
A.0 Đề bài
Cài JDK, thêm ...\jdk\bin vào Path, tạo thư
mục D:\THLTHDT, biên dịch và chạy chương trình đầu tiên từ
cmd.
A.1 Yêu cầu ẩn
- Máy có thể đã cài JRE (chạy được
java) nhưng không cójavac→ vẫn phải cài JDK. - Sau khi sửa
Path, phải đóng và mở lại cửa sổcmd, nếu không biến môi trường cũ vẫn còn. - Tên tệp không dấu, không khoảng trắng:
Chao.java, không phảiChào.javahaybai 1.java.
A.2 Kiểm tra đúng/sai
| Lệnh | Kết quả đúng | Nếu sai |
|---|---|---|
java -version |
java version "17.0.x" |
Chưa có JDK/JRE |
javac -version |
javac 17.0.x |
Có JRE nhưng chưa có JDK, hoặc chưa thêm bin vào
Path |
cd \THLTHDT |
Không báo lỗi | Chưa tạo thư mục |
javac Chao.java |
Im lặng = thành công | In lỗi cú pháp → sửa theo mục A.3 |
java Chao |
In ra dòng chữ | Could not find or load main class → sai tên lớp hoặc gõ
.class |
A.3 Ba lỗi môi trường hay gặp nhất
| Hiện tượng | Nguyên nhân | Cách sửa |
|---|---|---|
'javac' is not recognized as an internal or external command |
bin chưa vào Path |
Thêm C:\Program Files\Java\jdk-17\bin; mở lại
cmd |
error: file not found: Chao.java |
Notepad lưu thành Chao.java.txt |
Save as type = All Files |
Error: Main method not found in class Chao |
main sai chữ ký (thiếu String[] args hoặc
static) |
Sửa đúng public static void main(String[] args) |
Bài A1 — Chao2 (mục 2.3)
0. Đề bài
Viết chương trình in Chao <Tên>, với
<Tên> truyền vào từ dòng lệnh.
1. Yêu cầu ẩn
- Nếu người dùng chạy
java Chao2mà không truyền tên:args[0]sẽ némArrayIndexOutOfBoundsException. Phải kiểm traargs.lengthtrước. - Tên có thể có nhiều từ:
java Chao2 Nguyen Van A→ chỉ lấyargs[0]là "Nguyen"; muốn lấy hết thì nối các phần tử.
2. Input → Output
| Vào | Kiểu | Ghi chú | Ra |
|---|---|---|---|
args |
String[] |
có thể rỗng | Chao <ten> hoặc thông báo thiếu tham số |
3. Thiết kế
- Kiểm tra
args.length == 0→ in hướng dẫn,return. - Nối toàn bộ
argsbằng dấu cách (dùng vòng lặp, không dùngString.joinvì chưa học). - In
"Chao " + ten.
4. Code từng bước
Bước 1 — khung chương trình và kiểm tra tham số:
public class Chao2 {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("Cach dung: java Chao2 <ten>");
return; // thoát sớm, không chạy tiếp
}
}
}Tự kiểm tra: chạy java Chao2 phải in hướng dẫn, không
lỗi.
Bước 2 — nối các tham số và in:
String ten = "";
for (int i = 0; i < args.length; i++) {
ten += args[i];
if (i < args.length - 1) ten += " "; // thêm dấu cách giữa các từ
}
System.out.println("Chao " + ten);5. Lời giải hoàn chỉnh
// ===== Chao2.java =====
public class Chao2 {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("Cach dung: java Chao2 <ten>");
return;
}
String ten = "";
for (int i = 0; i < args.length; i++) {
ten += args[i];
if (i < args.length - 1) ten += " ";
}
System.out.println("Chao " + ten);
}
}6. Cách chạy
javac Chao2.java
java Chao2 Nam
java Chao2 Nguyen Van An
java Chao2
7. Kết quả chạy mẫu
Chao Nam
Chao Nguyen Van An
Cach dung: java Chao2 <ten>
8. Bảng kiểm thử
| # | Input | Kỳ vọng | Thực tế |
|---|---|---|---|
| 1 | java Chao2 Nam |
Chao Nam |
đạt |
| 2 | java Chao2 Nguyen Van An |
Chao Nguyen Van An |
đạt |
| 3 | java Chao2 |
in hướng dẫn, không lỗi | đạt |
| 4 | java Chao2 "" (chuỗi rỗng) |
Chao |
đạt |
9. Trace
args = ["Nguyen","Van","An"]:
Lượt i |
args[i] |
ten sau khi nối |
Có thêm dấu cách? |
|---|---|---|---|
| 0 | Nguyen | Nguyen |
có → Nguyen |
| 1 | Van | Nguyen Van |
có → Nguyen Van |
| 2 | An | Nguyen Van An |
không (i = length-1) |
10. Lỗi thường gặp
| Code sai | Thông báo | Nguyên nhân | Sửa |
|---|---|---|---|
String ten = args[0]; khi không truyền |
ArrayIndexOutOfBoundsException: 0 |
Không kiểm tra length |
if (args.length > 0) |
public static void main(String args) |
Error: Main method not found in class Chao2 |
Thiếu [] |
String[] args |
System.out.print("Chao " + args); |
Chao [Ljava.lang.String;@... |
In cả mảng | In từng phần tử |
Lưu Chao2.java.txt |
file not found |
Notepad tự thêm đuôi | Save as All Files |
java Chao2.class |
Could not find or load main class Chao2.class |
Khi chạy không ghi đuôi | java Chao2 |
11. Câu hỏi kiểm tra hiểu
- Vì sao
argscó sẵn dù ta không khai báo giá trị cho nó? - Nếu chạy
java Chao2 1 2 3,args.lengthbằng mấy? - Vì sao phải
returnsau khi in hướng dẫn?
12. Mở rộng
- In
Chao <ho> <ten>tách riêng họ và tên (dùngargs[0]là họ, các phần còn lại là tên). - Dùng
try/catchbắt lỗi khi người dùng truyền số thay vì chữ (kiến thức ngoài phạm vi, chỉ tham khảo).
TỰ KIỂM TRA 60 GIÂY: args là gì? Kiểm
tra gì trước khi dùng args[0]? Khi chạy có gõ
.class không?
Bài A2 — Đọc một số có một chữ số (mục 2.3)
0. Đề bài
Nhập một số có một chữ số (0–9), in ra cách đọc bằng chữ.
1. Yêu cầu ẩn
- Số ngoài 0–9 phải báo "khong hop le", không được im lặng.
- Nhập chữ thay vì số →
ScannernémInputMismatchException(chưa học try/catch nên chỉ cần ghi chú).
2. Input → Output
| Vào | Kiểu | Miền | Ra |
|---|---|---|---|
| số | int |
0..9 | tên chữ: khong, mot, hai, ... chin |
3. Thiết kế
Dùng switch vì là so bằng với danh sách giá trị
rời rạc (buổi 6). default xử lý ngoài miền.
4. Code từng bước
Bước 1 — nhập số, kiểm tra miền:
Scanner sc = new Scanner(System.in);
System.out.print("Nhap mot chu so (0-9): ");
int n = sc.nextInt();
if (n < 0 || n > 9) {
System.out.println("Khong hop le");
return;
}Bước 2 — switch in tên:
switch (n) {
case 0: System.out.println("khong"); break;
case 1: System.out.println("mot"); break;
case 2: System.out.println("hai"); break;
case 3: System.out.println("ba"); break;
case 4: System.out.println("bon"); break;
case 5: System.out.println("nam"); break;
case 6: System.out.println("sau"); break;
case 7: System.out.println("bay"); break;
case 8: System.out.println("tam"); break;
case 9: System.out.println("chin"); break;
}5. Lời giải hoàn chỉnh
// ===== DocSo.java =====
import java.util.Scanner;
public class DocSo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Nhap mot chu so (0-9): ");
int n = sc.nextInt();
if (n < 0 || n > 9) {
System.out.println("Khong hop le");
} else {
switch (n) {
case 0: System.out.println("khong"); break;
case 1: System.out.println("mot"); break;
case 2: System.out.println("hai"); break;
case 3: System.out.println("ba"); break;
case 4: System.out.println("bon"); break;
case 5: System.out.println("nam"); break;
case 6: System.out.println("sau"); break;
case 7: System.out.println("bay"); break;
case 8: System.out.println("tam"); break;
default: System.out.println("chin"); break;
}
}
sc.close();
}
}Chú ý:
defaultở đây chỉ còn nhận9vì đã chặn ngoài miền — hợp lệ nhưng dễ gây nhầm. Cách an toàn hơn: vẫn viếtcase 9: ... break;vàdefault: System.out.println("Khong hop le");.
6. Cách chạy
javac DocSo.java
java DocSo
7. Kết quả chạy mẫu
Nhap mot chu so (0-9): 7
bay
8. Bảng kiểm thử
| # | Input | Kỳ vọng |
|---|---|---|
| 1 | 7 | bay |
| 2 | 0 | khong |
| 3 | -1 | Khong hop le |
| 4 | 10 | Khong hop le |
9. Trace
n = 7 → vào case 7 → in bay →
gặp break → thoát switch. Nếu bỏ tất cả
break: n = 7 in bay tam chin
(fall-through, buổi 6).
10. Lỗi thường gặp
| Code sai | Thông báo | Sửa |
|---|---|---|
switch (n) { case 0: ... } thiếu
break |
Không lỗi, in thừa | Thêm break |
if (n = 7) |
incompatible types: int cannot be converted to boolean |
== |
Quên import java.util.Scanner; |
cannot find symbol: class Scanner |
Thêm import |
Nhập 7.5 |
InputMismatchException |
Chỉ nhập số nguyên |
11. Câu hỏi kiểm tra hiểu
- Vì sao bài này dùng
switchmà không dùng 10 câuif? - Nếu bỏ
default, nhập 9 thì in gì? breakbỏ đi thì chương trình sai ở đâu?
12. Mở rộng
- Mở rộng cho 2 chữ số (0–99): tách hàng chục và hàng đơn vị bằng
/ 10và% 10. - Đọc số âm: xử lý dấu trước rồi đọc trị tuyệt đối.
Bài A3 — Hình tròn (mục 2.3)
0. Đề bài
Nhập bán kính, tính và in diện tích, chu vi hình tròn.
1. Yêu cầu ẩn
- Bán kính ≤ 0 phải báo lỗi (hình tròn bán kính âm vô nghĩa).
- Dùng
doublecho mọi phép tính, nếu dùngintsẽ mất phần lẻ. - Làm tròn khi in để không ra
28.274333882308138.
2. Input → Output
| Vào | Kiểu | Ràng buộc | Ra |
|---|---|---|---|
r |
double |
r > 0 |
diện tích πr², chu vi 2πr |
3. Thiết kế
- Nhập
r. - Kiểm tra
r <= 0→ báo lỗi, thoát. - Tính
dienTich = Math.PI * r * r,chuVi = 2 * Math.PI * r. - In, làm tròn 2 chữ số:
Math.round(x * 100) / 100.0.
4. Code từng bước
Bước 1 — nhập và kiểm tra:
Scanner sc = new Scanner(System.in);
System.out.print("Nhap ban kinh: ");
double r = sc.nextDouble();
if (r <= 0) {
System.out.println("Ban kinh phai duong");
return;
}Bước 2 — tính và in:
double dienTich = Math.PI * r * r;
double chuVi = 2 * Math.PI * r;
System.out.println("Dien tich: " + Math.round(dienTich * 100) / 100.0);
System.out.println("Chu vi : " + Math.round(chuVi * 100) / 100.0);5. Lời giải hoàn chỉnh
// ===== HinhTron.java =====
import java.util.Scanner;
public class HinhTron {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Nhap ban kinh: ");
double r = sc.nextDouble();
if (r <= 0) {
System.out.println("Ban kinh phai duong");
sc.close();
return;
}
double dienTich = Math.PI * r * r;
double chuVi = 2 * Math.PI * r;
System.out.println("Dien tich: " + Math.round(dienTich * 100) / 100.0);
System.out.println("Chu vi : " + Math.round(chuVi * 100) / 100.0);
sc.close();
}
}6. Cách chạy
javac HinhTron.java
java HinhTron
7. Kết quả chạy mẫu
Nhap ban kinh: 3
Dien tich: 28.27
Chu vi : 18.85
Kiểm tra tay: π·3² = 9π ≈ 28.2743 → 28.27 ✓;
2π·3 = 6π ≈ 18.8496 → 18.85 ✓.
8. Bảng kiểm thử
| # | Input | Kỳ vọng |
|---|---|---|
| 1 | 3 | 28.27 / 18.85 |
| 2 | 1 | 3.14 / 6.28 |
| 3 | 0 | "Ban kinh phai duong" |
| 4 | -2 | "Ban kinh phai duong" |
9. Trace
| Lệnh | r |
dienTich |
chuVi |
|---|---|---|---|
nextDouble() |
3.0 | — | — |
π*r*r |
3.0 | 28.274333882308138 | — |
2*π*r |
3.0 | 28.274333882308138 | 18.84955592153876 |
| in làm tròn | 28.27 | 18.85 |
10. Lỗi thường gặp
| Code sai | Thông báo | Sửa |
|---|---|---|
int r = sc.nextInt(); rồi Math.PI*r*r |
Kết quả mất phần lẻ | double |
r * r * 3.14 |
Không lỗi, nhưng kém chính xác | Dùng Math.PI |
Math.round(x) |
In 28.0 thay vì 28.27 | Math.round(x*100)/100.0 |
Thiếu import java.util.Scanner |
cannot find symbol |
Thêm import |
11. Câu hỏi kiểm tra hiểu
- Vì sao phải ép
Math.round(...)vềdoublebằng/ 100.0chứ không/ 100? - Nếu không kiểm tra
r <= 0, chương trình in gì vớir = -2? Có sai không? Math.PIthuộc lớp nào, có cầnimportkhông?
12. Mở rộng
- Tính thêm thể tích hình cầu
4/3·πr³(chú ý4/3là chia nguyên → viết4.0/3). - Nhập đường kính thay bán kính.
Bài A4 — Sắp xếp mảng ngẫu nhiên (mục 2.3)
0. Đề bài
Tạo mảng số nguyên ngẫu nhiên, sắp xếp tăng dần và in ra.
1. Yêu cầu ẩn
- "Ngẫu nhiên" → mỗi lần chạy kết quả khác nhau; muốn tái lập thì dùng
Randomvới seed. - Phải in trước và sau khi sắp xếp để thấy tác dụng.
- Không dùng
Arrays.sortnếu giảng viên yêu cầu tự viết thuật toán (đề bài tập về thuật toán).
2. Input → Output
| Vào | Kiểu | Miền | Ra |
|---|---|---|---|
n |
int |
1..100 | mảng trước và sau khi sắp xếp |
3. Thiết kế
- Sinh
nsố bằng(int)(Math.random() * 100)→ 0..99. - In mảng ban đầu.
- Bubble sort (buổi 4).
- In mảng sau khi sắp xếp.
4. Code từng bước
Bước 1 — sinh mảng và in:
int n = 10;
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = (int) (Math.random() * 100);
}
for (int i = 0; i < n; i++) System.out.print(a[i] + " ");
System.out.println();Bước 2 — sắp xếp nổi bọt:
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - 1 - i; j++) {
if (a[j] > a[j + 1]) {
int tmp = a[j];
a[j] = a[j + 1];
a[j + 1] = tmp;
}
}
}Bước 3 — in lại.
5. Lời giải hoàn chỉnh
// ===== SapXepNgauNhien.java =====
public class SapXepNgauNhien {
public static void main(String[] args) {
int n = 10;
int[] a = new int[n];
// 1. sinh ngau nhien 0..99
for (int i = 0; i < n; i++) {
a[i] = (int) (Math.random() * 100);
}
System.out.print("Truoc khi sap xep: ");
for (int i = 0; i < n; i++) System.out.print(a[i] + " ");
System.out.println();
// 2. sap xep noi bot tang dan
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - 1 - i; j++) {
if (a[j] > a[j + 1]) {
int tmp = a[j];
a[j] = a[j + 1];
a[j + 1] = tmp;
}
}
}
System.out.print("Sau khi sap xep : ");
for (int i = 0; i < n; i++) System.out.print(a[i] + " ");
System.out.println();
}
}6. Cách chạy
javac SapXepNgauNhien.java
java SapXepNgauNhien
7. Kết quả chạy mẫu (một lần chạy, số sẽ khác mỗi lần)
Truoc khi sap xep: 42 7 91 15 63 3 88 24 56 71
Sau khi sap xep : 3 7 15 24 42 56 63 71 88 91
Không được lấy dãy số này làm "kết quả đúng" — hãy kiểm tra tính chất: sau khi sắp xếp, dãy không giảm và có đúng 10 phần tử như ban đầu (so khớp tổng hai dãy phải bằng nhau).
8. Bảng kiểm thử
| # | Tình huống | Kỳ vọng |
|---|---|---|
| 1 | n = 10 bình thường | dãy sau sắp xếp không giảm, cùng đa tập phần tử |
| 2 | n = 1 | in 1 phần tử, không lỗi |
| 3 | Mảng toàn số bằng nhau | không đổi |
| 4 | n = 0 | không in gì, không lỗi (vòng lặp không chạy) |
9. Trace (mảng nhỏ
{3, 1, 2} để dễ thấy)
Lượt i |
j |
So sánh | Đổi chỗ | Mảng |
|---|---|---|---|---|
| — | — | — | — | 3 1 2 |
| 0 | 0 | 3 > 1 | có | 1 3 2 |
| 0 | 1 | 3 > 2 | có | 1 2 3 |
| 1 | 0 | 1 > 2 | không | 1 2 3 |
10. Lỗi thường gặp
| Code sai | Thông báo / hiện tượng | Sửa |
|---|---|---|
a[j] = a[j+1]; a[j+1] = a[j]; |
Hai phần tử bằng nhau | Dùng tmp |
j < n - i |
ArrayIndexOutOfBoundsException tại
a[j+1] |
j < n - 1 - i |
(int) Math.random() * 100 |
Luôn bằng 0 | (int)(Math.random()*100) |
for (i = 0; i < n; i++) không khai báo
i |
cannot find symbol |
for (int i = ...) |
11. Câu hỏi kiểm tra hiểu
- Vì sao
Math.random()phải nhân trước rồi mới ép(int)? - Vì sao vòng trong chỉ chạy
n-1-ilần? - Nếu mảng đã sắp xếp sẵn, thuật toán còn đổi chỗ lần nào không?
12. Mở rộng
- Sắp xếp giảm dần: chỉ đổi
a[j] > a[j+1]thành<. - Đếm số lần đổi chỗ để so sánh "mảng gần đúng thứ tự" và "mảng ngẫu nhiên".
- Dùng
java.util.Arrays.sort(a)để đối chiếu kết quả (thư viện chuẩn, được phép).
TỰ KIỂM TRA 60 GIÂY: vì sao cần biến
tmp? Math.random() trả về kiểu gì? Vì sao phải
in cả trước và sau?
Bài A5 — Tính
n! với n từ dòng lệnh (mục 2.4, Bài 1)
0. Đề bài
Tính giai thừa n! với n truyền vào từ dòng
lệnh.
1. Yêu cầu ẩn
n < 0không có giai thừa → báo lỗi.0! = 1theo quy ước — rất hay bị bỏ sót.13!đã vượtint(13! = 6 227 020 800 > 2 147 483 647) → phải dùnglong.- Phải chuyển
StringtừargssangintbằngInteger.parseInt.
2. Input → Output
| Vào | Kiểu | Ràng buộc | Ra |
|---|---|---|---|
args[0] |
String → int |
0 ≤ n ≤ 20 (với long) |
n! |
3. Thiết kế
- Kiểm tra có tham số.
int n = Integer.parseInt(args[0]);- Nếu
n < 0→ báo lỗi, thoát. long kq = 1; for (int i = 2; i <= n; i++) kq *= i;- In.
4. Code từng bước
Bước 1 — đọc và kiểm tra:
if (args.length == 0) {
System.out.println("Cach dung: java GiaiThua <n>");
return;
}
int n = Integer.parseInt(args[0]);
if (n < 0) {
System.out.println("n phai >= 0");
return;
}Bước 2 — tính bằng long và in:
long kq = 1;
for (int i = 2; i <= n; i++) {
kq *= i;
}
System.out.println(n + "! = " + kq);5. Lời giải hoàn chỉnh
// ===== GiaiThua.java =====
public class GiaiThua {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("Cach dung: java GiaiThua <n>");
return;
}
int n = Integer.parseInt(args[0]);
if (n < 0) {
System.out.println("n phai >= 0");
return;
}
long kq = 1;
for (int i = 2; i <= n; i++) { // bat dau tu 2: 0! va 1! deu = 1
kq *= i;
}
System.out.println(n + "! = " + kq);
}
}6. Cách chạy
javac GiaiThua.java
java GiaiThua 5
java GiaiThua 0
java GiaiThua 20
7. Kết quả chạy mẫu
5! = 120
0! = 1
20! = 2432902008176640000
Kiểm tra: 5! = 120 ✓;
20! = 2 432 902 008 176 640 000 ✓ (vừa
long).
8. Bảng kiểm thử
| # | Input | Kỳ vọng |
|---|---|---|
| 1 | 5 | 5! = 120 |
| 2 | 0 | 0! = 1 |
| 3 | -3 | n phai >= 0 |
| 4 | 13 | 6227020800 (chỉ đúng nếu dùng long) |
9. Trace
n = 5:
i |
kq trước |
kq sau |
|---|---|---|
| — | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 6 |
| 4 | 6 | 24 |
| 5 | 24 | 120 |
10. Lỗi thường gặp
| Code sai | Thông báo / hiện tượng | Sửa |
|---|---|---|
int kq = 1; với n = 13 |
Ra số âm (-559939584) do tràn |
long |
Integer.parseint(args[0]) |
cannot find symbol: method parseint |
parseInt |
for (i = 1; i < n; i++) |
Thiếu một thừa số (5! ra 24) |
i <= n |
Truyền chữ: java GiaiThua abc |
NumberFormatException |
Kiểm tra dữ liệu (nâng cao: try/catch) |
Không kiểm tra args.length |
ArrayIndexOutOfBoundsException |
Kiểm tra trước |
11. Câu hỏi kiểm tra hiểu
- Vì sao vòng lặp bắt đầu từ 2 mà vẫn đúng với
0!và1!? - Vì sao
13!là "cột mốc" của kiểuint? n = 21thìlongcó đủ không? (21! ≈ 5.1×10¹⁹ > 9.2×10¹⁸→ tràn)
12. Mở rộng
- Tính tổng
S = 1 + 1/1! + 1/2! + ... + 1/n!(dùngdouble). - Kiểm tra tràn: nếu
kq > Long.MAX_VALUE / ithì báo "qua lon".
Bài A6 — Số nguyên tố trong mảng (mục 2.4, Bài 2)
0. Đề bài
Nhập mảng n số nguyên, liệt kê các số nguyên tố có trong
mảng; bổ sung thông báo mảng có bao nhiêu số nguyên tố.
1. Yêu cầu ẩn
n ≤ 0phải xử lý (không cấp phát mảng âm được).- Số 0 và 1 không phải nguyên tố; số âm không phải nguyên tố.
- Đếm và in đúng số lượng.
2. Input → Output
| Vào | Kiểu | Miền | Ra |
|---|---|---|---|
n |
int |
1..100 | danh sách số nguyên tố + số lượng |
a[i] |
int |
bất kỳ |
3. Thiết kế
- Hàm
laNguyenTo(int n)dùng vòng lặp đến√n. - Hàm
nhapMang,inMangđể tách trách nhiệm. - Đếm trong lúc duyệt.
4. Code từng bước
Bước 1 — hàm kiểm tra nguyên tố (thuộc lòng):
public static boolean laNguyenTo(int n) {
if (n < 2) return false; // 0, 1 va so am
for (int i = 2; i <= Math.sqrt(n); i++) {
if (n % i == 0) return false; // co uoc -> khong nguyen to
}
return true;
}Bước 2 — nhập mảng:
int[] a = new int[n];
for (int i = 0; i < n; i++) {
System.out.print("a[" + i + "] = ");
a[i] = sc.nextInt();
}Bước 3 — duyệt, in và đếm:
int dem = 0;
for (int i = 0; i < n; i++) {
if (laNguyenTo(a[i])) {
System.out.print(a[i] + " ");
dem++;
}
}
System.out.println("\nCo " + dem + " so nguyen to");5. Lời giải hoàn chỉnh
// ===== NguyenToTrongMang.java =====
import java.util.Scanner;
public class NguyenToTrongMang {
public static boolean laNguyenTo(int n) {
if (n < 2) return false;
for (int i = 2; i <= Math.sqrt(n); i++) {
if (n % i == 0) return false;
}
return true;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Nhap n: ");
int n = sc.nextInt();
if (n <= 0) {
System.out.println("n phai > 0");
sc.close();
return;
}
int[] a = new int[n];
for (int i = 0; i < n; i++) {
System.out.print("a[" + i + "] = ");
a[i] = sc.nextInt();
}
System.out.print("Cac so nguyen to: ");
int dem = 0;
for (int i = 0; i < n; i++) {
if (laNguyenTo(a[i])) {
System.out.print(a[i] + " ");
dem++;
}
}
System.out.println();
System.out.println("Co " + dem + " so nguyen to");
sc.close();
}
}6. Cách chạy
javac NguyenToTrongMang.java
java NguyenToTrongMang
7. Kết quả chạy mẫu
Nhap n: 6
a[0] = 2
a[1] = 3
a[2] = 4
a[3] = 5
a[4] = 10
a[5] = 11
Cac so nguyen to: 2 3 5 11
Co 4 so nguyen to
8. Bảng kiểm thử
| # | Mảng | Kỳ vọng |
|---|---|---|
| 1 | 2 3 4 5 10 11 |
2 3 5 11, 4 số |
| 2 | 0 1 |
không có, 0 số |
| 3 | -7 7 |
7, 1 số |
| 4 | 97 |
97, 1 số |
9. Trace
laNguyenTo(11): i chạy 2, 3
(√11 ≈ 3.31), cả hai 11 % i ≠ 0 →
true. laNguyenTo(9): i = 2 không
chia hết; i = 3, 9 % 3 == 0 →
false ngay.
10. Lỗi thường gặp
| Code sai | Hiện tượng | Sửa |
|---|---|---|
if (n == 1) return false; |
Số 0 và số âm bị coi là nguyên tố | if (n < 2) return false; |
for (i = 2; i < n; i++) |
Chạy chậm nhưng vẫn đúng | Dùng Math.sqrt |
return true; khi chia hết |
Kết quả ngược | return false; |
Quên break khi đếm |
Không ảnh hưởng, nhưng khó đọc | Tách hàm |
n <= 0 vẫn new int[n] |
NegativeArraySizeException |
Kiểm tra trước |
11. Câu hỏi kiểm tra hiểu
- Vì sao chỉ cần duyệt đến
√nmà vẫn kết luận đúng? - Vì sao
1không phải số nguyên tố? - Nếu mảng toàn số âm, hàm trả gì? Vì sao?
12. Mở rộng
- In thêm vị trí của số nguyên tố.
- Đếm số nguyên tố phân biệt (không trùng) — cần thêm mảng đánh dấu.
- Tìm số nguyên tố lớn nhất trong mảng.
Bài A7 — Fibonacci trong mảng (mục 2.4, Bài 3)
0. Đề bài
Nhập mảng n số nguyên, liệt kê các số Fibonacci có trong
mảng.
1. Yêu cầu ẩn
- Dãy Fibonacci:
0, 1, 1, 2, 3, 5, 8, 13, 21, ...— phải sinh dãy đến khi vượt giá trị lớn nhất trong mảng rồi mới kiểm tra, hoặc kiểm tra bằng cách sinh dần. - Không được sinh vô hạn; cần điều kiện dừng.
- Số âm không phải Fibonacci.
2. Input → Output
| Vào | Kiểu | Ra |
|---|---|---|
mảng n số nguyên |
int[] |
các phần tử là số Fibonacci (theo thứ tự trong mảng) |
3. Thiết kế
Cách đơn giản và đúng: với mỗi a[i], kiểm tra bằng hàm
laFibonacci sinh dãy từ 0, 1 đến khi ≥ giá
trị cần kiểm tra.
4. Code từng bước
Bước 1 — hàm kiểm tra:
public static boolean laFibonacci(int x) {
if (x < 0) return false;
int a = 0, b = 1;
while (a < x) {
int tiep = a + b;
a = b;
b = tiep;
}
return a == x; // dung lai khi a >= x
}Bước 2 — duyệt mảng, in.
for (int i = 0; i < n; i++) {
if (laFibonacci(a[i])) System.out.print(a[i] + " ");
}5. Lời giải hoàn chỉnh
// ===== FibonacciTrongMang.java =====
import java.util.Scanner;
public class FibonacciTrongMang {
public static boolean laFibonacci(int x) {
if (x < 0) return false;
int a = 0, b = 1;
while (a < x) {
int tiep = a + b;
a = b;
b = tiep;
}
return a == x;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Nhap n: ");
int n = sc.nextInt();
if (n <= 0) {
System.out.println("n phai > 0");
sc.close();
return;
}
int[] a = new int[n];
for (int i = 0; i < n; i++) {
System.out.print("a[" + i + "] = ");
a[i] = sc.nextInt();
}
System.out.print("Cac so Fibonacci: ");
for (int i = 0; i < n; i++) {
if (laFibonacci(a[i])) System.out.print(a[i] + " ");
}
System.out.println();
sc.close();
}
}6. Cách chạy
javac FibonacciTrongMang.java
java FibonacciTrongMang
7. Kết quả chạy mẫu
Nhap n: 7
a[0] = 1
a[1] = 2
a[2] = 4
a[3] = 5
a[4] = 8
a[5] = 13
a[6] = 20
Cac so Fibonacci: 1 2 5 8 13
8. Bảng kiểm thử
| # | Giá trị | laFibonacci |
|---|---|---|
| 1 | 0 | true |
| 2 | 1 | true |
| 3 | 4 | false |
| 4 | 13 | true |
| 5 | -3 | false |
9. Trace laFibonacci(8)
| Bước | a |
b |
a < 8? |
|---|---|---|---|
| đầu | 0 | 1 | đúng |
| 1 | 1 | 1 | đúng |
| 2 | 1 | 2 | đúng |
| 3 | 2 | 3 | đúng |
| 4 | 3 | 5 | đúng |
| 5 | 5 | 8 | đúng |
| 6 | 8 | 13 | sai → dừng, a == 8 →
true |
10. Lỗi thường gặp
| Code sai | Hiện tượng | Sửa |
|---|---|---|
while (true) { ... } không điều kiện dừng |
Treo với số không phải Fibonacci | Dừng khi a >= x |
if (a == x) return true; đặt trong
vòng lặp không có break |
Không sai nhưng thừa | Kiểm tra sau vòng lặp |
Dùng a < x mà quên trường hợp
x = 0 |
0 vẫn đúng vì vòng lặp không chạy |
Kiểm tra a == 0 |
Tràn int khi sinh dãy lớn |
Số âm xuất hiện | Dùng long hoặc chặn x |
11. Câu hỏi kiểm tra hiểu
- Vì sao vòng lặp dừng ở
a < xmà vẫn kiểm tra đúngx = 8? - Nếu
x = 1, vòng lặp chạy mấy lần? - Vì sao phải kiểm tra
x < 0trước?
12. Mở rộng
- In vị trí của các số Fibonacci trong mảng.
- In các số Fibonacci nhỏ hơn một giá trị
Mcho trước (không cần mảng). - Tìm số Fibonacci lớn nhất trong mảng.