Số Armstrong, còn được biết đến với tên gọi số thủy tiên hoặc số Narcissistic, là một số nguyên dương có n chữ số sao cho tổng lũy thừa bậc n của từng chữ số bằng chính số đó. Ví dụ, với số có 3 chữ số, tổng lập phương của các chữ số phải bằng giá trị của số ấy. Bài viết này sẽ hướng dẫn cách xây dựng chương trình trên nền tảng Visual Basic .NET để xác định các số thỏa mãn điều kiện này.
Nguyên lý hoạt động của thuật toán
Để tìm ra các số Armstrong, phương pháp phổ biến nhất là duyệt toàn bộ (brute-force) trong một khoảng xác định. Với một số có n chữ số, khoảng giá trị sẽ bắt đầu từ $10^{n-1}$ và kết thúc tại $10^n - 1$. Với mỗi giá trị trong khoảng này, chương trình sẽ tách từng chữ số, tính lũy thừa bậc n và cộng dồn lại. Nếu tổng thu được trùng với số ban đầu, đó là một số Armstrong.
Ngôn ngữ Visual Basic .NET cung cấp các toán tử số học và cấu trúc vòng lặp linh hoạt, giúp việc triển khai logic này trở nên đơn giản và dễ đọc. Chúng ta có thể sử dụng phép chia lấy dư (Mod) để lấy chữ số cuối cùng và phép chia nguyên (\) để loại bỏ chữ số đó khỏi số gốc.
Triển khai cố định số chữ số
Trong ví dụ đầu tiên, chúng ta sẽ thiết lập sẵn số chữ số là 3. Chương trình sẽ quét toàn bộ các số từ 100 đến 999. Để mã nguồn gọn gàng hơn, logic kiểm tra sẽ được tách riêng vào một hàm phụ trợ.
Imports System
Module KiemTraSo
Sub Main()
Dim bac As Integer = 3
Dim danhSachKetQua As New List(Of Integer)()
Dim dau As Integer = CInt(Math.Pow(10, bac - 1))
Dim cuoi As Integer = CInt(Math.Pow(10, bac)) - 1
For giaTri As Integer = dau To cuoi
If IsArmstrong(giaTri, bac) Then
danhSachKetQua.Add(giaTri)
End If
Next
Console.WriteLine("Danh sach so Armstrong (3 chu so):")
For Each so In danhSachKetQua
Console.WriteLine(so)
Next
End Sub
Function IsArmstrong(so As Integer, mu As Integer) As Boolean
Dim tong As Integer = 0
Dim temp As Integer = so
Do While temp > 0
Dim chuso As Integer = temp Mod 10
tong += CInt(Math.Pow(chuso, mu))
temp \= 10
Loop
Return tong = so
End Function
End Module
Đoạn mã trên khởi tạo khoảng chạy dựa trên biến `bac`. Hàm `IsArmstrong` chịu trách nhiệm tính toán tổng lũy thừa. Việc sử dụng `Math.Pow` thay cho toán tử `^` trực tiếp giúp tăng tính tường minh khi làm việc với kiểu dữ liệu số thực trước khi ép kiểu về nguyên.
Mở rộng cho số chữ số bất kỳ
Để chương trình linh hoạt hơn, chúng ta có thể cho phép người dùng nhập vào số lượng chữ số mong muốn qua giao diện console. Logic xử lý vẫn giữ nguyên, chỉ thay đổi cách khởi tạo giá trị n và thêm phần đọc dữ liệu đầu vào.
Imports System
Module KiemTraSo
Sub Main()
Console.Write("Nhap so chu so (n): ")
Dim input As String = Console.ReadLine()
Dim bac As Integer = 0
If Integer.TryParse(input, bac) AndAlso bac > 0 Then
Dim ketQua As New List(Of Integer)()
Dim minVal As Integer = CInt(Math.Pow(10, bac - 1))
Dim maxVal As Integer = CInt(Math.Pow(10, bac)) - 1
For i As Integer = minVal To maxVal
If TinhTongLuyThua(i, bac) = i Then
ketQua.Add(i)
End If
Next
Console.WriteLine("Ket qua tim duoc:")
For Each val In ketQua
Console.WriteLine(val)
Next
Else
Console.WriteLine("Gia tri nhap khong hop le.")
End If
Console.ReadLine()
End Sub
Function TinhTongLuyThua(soGoc As Integer, mu As Integer) As Integer
Dim tongLuyThua As Integer = 0
Dim bienTam As Integer = soGoc
While bienTam >= 1
Dim chuSoHang As Integer = bienTam Mod 10
tongLuyThua += CInt(Math.Pow(chuSoHang, mu))
bienTam \= 10
End While
Return tongLuyThua
End Function
End Module
Trong phiên bản này, hàm `Integer.TryParse` được sử dụng để đảm bảo dữ liệu đầu vào hợp lệ trước khi thực thi vòng lặp. Biến `minVal` và `maxVal` xác định ranh giới duyệt dựa trên lũy thừa của 10. Hàm `TinhTongLuyThua` thực hiện việc tách số và tính toán tổng, trả về giá trị để so sánh với số gốc ngay trong vòng lặp chính.