Giúp lập công thức đếm chữ số lẻ, chữ số chẵn trong các ô. Em cảm ơn

Liên hệ QC

Lan Phương 9

Thành viên mới
Tham gia
9/4/22
Bài viết
4
Được thích
0
untitled-png.274242
Untitled.png
3468748Lẻ ?Chẵn ?
35598205
863202316
4107923

Ví dụ :
Ô A1 có 1 chữ số lẻ và 2 chữ số chẵn, ô B1 có 1 chữ số lẻ và 3 chữ số chẵn.
Ô A2 có 2 chữ số lẻ, ô B2 có 3 chữ số lẻ và 3 chữ số chẵn.
Số 0 coi là chữ số chẵn.
Viết công thức
Có tổng cộng bao nhiêu "chữ số lẻ", bao nhiêu "chữ số chẵn" trong các ô trên ?
 

File đính kèm

Lần chỉnh sửa cuối:
Ô A1 có 1 chữ số lẻ và 2 chữ số chẵn, ô B1 có 1 chữ số lẻ và 3 chữ số chẵn.
Ô A2 có 2 chữ số lẻ, ô B2 có 3 chữ số lẻ và 3 chữ số chẵn.
Số 0 coi là chữ số chẵn.
Viết công thức
Có tổng cộng bao nhiêu "chữ số lẻ", bao nhiêu "chữ số chẵn" trong các ô trên ?
Chào bạn,

Trong C1 và D1, kết quả mong muốn của bạn là bao nhiêu?

.
 
Bạn nên đổi tiêu đề thành: "Giúp lập công thức đếm số chẵn, số lẻ" cho nó gọn.
Code của bạn,nên thay dòng:

If tam Mod 2 = so Then dem_so = dem_so + 1

bằng dòng:

If Mid(tam, i, 1) Mod 2 = so Then dem_so = dem_so + 1

Hoặc nếu có excel 365, có thể dùng công thức này để đếm số lẻ:

=SUMPRODUCT(--ISODD(MID(TEXTJOIN("",1,$A$1:$B$4),SEQUENCE(LEN(TEXTJOIN("",1,$A$1:$B$4))),1)))

.
 
Code của bạn,nên thay dòng:

If tam Mod 2 = so Then dem_so = dem_so + 1

bằng dòng:

If Mid(tam, i, 1) Mod 2 = so Then dem_so = dem_so + 1

Hoặc nếu có excel 365, có thể dùng công thức này để đếm số lẻ:

=SUMPRODUCT(--ISODD(MID(TEXTJOIN("",1,$A$1:$B$4),SEQUENCE(LEN(TEXTJOIN("",1,$A$1:$B$4))),1)))
Dạ cảm ơn anh, em thay rồi anh ạ. lúc em thấy anh hỏi kết quả trong 2 ô mong muốn là bao nhiêu thì em kiểm tra lại, thấy code cũ chưa đúng.
 
Lần chỉnh sửa cuối:
Dạ cảm ơn anh, em thay rồi anh ạ. lức em thấy anh hỏi kết quả trong 2 ô mong muốn là bao nhiêu thì em kiểm tra lại, thấy code cũ chưa đúng.
Code theo kiểu của bạn là kiểu "chữ ký GPE" (*1)

Code theo kiểu bình thường thì người ta code một hàm trả về cả hai số đếm. Và một hàm khác chọn số.
Viết hai hàm riêng biệt thế này được cái lợi là bạn có thể goi thẳng hàm con:
Nếu lấy hai lần riêng thì dùng hàm Index đẻ lấ phần tử thứ nhất hay thứ hai.
Nếu lấy một lần cả hai số thì chọn 2 ô và Ctrl+Shift+Enter

Function DemChanLe(ByVal so) As Variant
' ham xet so chu so chan le trong mot so
' tra ve mot array:
' voi phan tư thư nhat là so chu so le, phan tu thu hai la so chan
Dim a(1 To 2) As Long, s As String, i As Long
s = Trim(CStr(so))
For i = 1 To Len(s)
If (CInt(Mid(s, i, 1)) And 1) Then
a(1) = a(1) + 1
Else
a(2) = a(2) + 1
End If
Next i
DemChanLe = a
End Function

Function DemSoChanLe(ByVal so, Optional ByVal ChanLe=0) As Long
' ham dem so chu so chan hoac le trong mot so
' tra ve so le neu ChanLe là so le, va nguoc lai
DemSoChanLe = DemChanLe(so)(IIf(ChanLe And 1, 1, 2))
End Function

(*1) GPE's signature: trong tiếng Anh, chữ ký là ý nói cách làm đặc thù của một cá thể.

(*2) toán tử AND: tôi có nói một vài lần rồi. Khi học lập trình qua hết mức căn bản, vào mức khá rồi thì người ta phải học những mánh khoé tính toán, xem xét dữ liệu. Xét chẵn lẻ, gọt bỏ thập phân, chia 0,... là những mánh khoé cần thuộc lòng.
Trong VBA, And là toán tử bit (a And b có nghĩa là mỗi bit của a sẽ And với bit tương ứng bên b). Vì vây con toán xét chẵn lẻ của VBA rất hiệu quả khi ta chỉ cần xét bít 1.
 
Lần chỉnh sửa cuối:
Code theo kiểu của bạn là kiểu "chữ ký GPE" (*1)

Code theo kiểu bình thường thì người ta code một hàm trả về cả hai số đếm. Và một hàm khác chọn số.
Viết hai hàm riêng biệt thế này được cái lợi là bạn có thể goi thẳng hàm con:
Nếu lấy hai lần riêng thì dùng hàm Index đẻ lấ phần tử thứ nhất hay thứ hai.
Nếu lấy một lần cả hai số thì chọn 2 ô và Ctrl+Shift+Enter

Function DemChanLe(ByVal so) As Variant
' ham xet so chu so chan le trong mot so
' tra ve mot array:
' voi phan tư thư nhat là so chu so le, phan tu thu hai la so chan
Dim a(1 To 2) As Long, s As String, i As Long
s = Trim(CStr(so))
For i = 1 To Len(s)
If (CInt(Mid(s, i, 1)) And 1) Then
a(1) = a(1) + 1
Else
a(2) = a(2) + 1
End If
Next i
DemChanLe = a
End Function

Function DemSoChanLe(ByVal so, Optional ByVal ChanLe=0) As Long
' ham dem so chu so chan hoac le trong mot so
' tra ve so le neu ChanLe là so le, va nguoc lai
DemSoChanLe = DemChanLe(so)(IIf(ChanLe And 1, 1, 2))
End Function

(*1) GPE's signature: trong tiếng Anh, chữ ký là ý nói cách làm đặc thù của một cá thể.

(*2) toán tử AND: tôi có nói một vài lần rồi. Khi học lập trình qua hết mức căn bản, vào mức khá rồi thì người ta phải học những mánh khoé tính toán, xem xét dữ liệu. Xét chẵn lẻ, gọt bỏ thập phân, chia 0,... là những mánh khoé cần thuộc lòng.
Trong VBA, And là toán tử bit (a And b có nghĩa là mỗi bit của a sẽ And với bit tương ứng bên b). Vì vây con toán xét chẵn lẻ của VBA rất hiệu quả khi ta chỉ cần xét bít 1.
Vận hành của toán tử And đặc biệt và phức tạp nên ít người dùng cho "số And Số" bạn không giải thích chi tiết sợ nhiều người không hiểu và lại đi vào quên lãng như những lần trước :)
 
Vận hành của toán tử And đặc biệt và phức tạp nên ít người dùng cho "số And Số" bạn không giải thích chi tiết sợ nhiều người không hiểu và lại đi vào quên lãng như những lần trước :)
THì giải thích:

Nên nhớ, bên trong máy thì các số được diễn đạt bằng hệ nhị phân, điển hình Integer có 16 bít, Long có 32 bít.
Khái niệm các hàng đơn vị:
- hệ thập phan có hàng đơn vị, hàng chục, hàng trăm,... Điển hình hàng chục là chữ số thứ 2 đếm từ bên phải.
Con số 123 là 1 hàng trăm, 2 hàng chục, 3 3 hàng đơn vị.
- hệ nhị phân có hàng 1, hàng 2, 4, 8, ... Điển hình hàng 4 là bit thứ 3 đếm từ nên phải.
Con số 1101 là 1 hàng 8, 1 hàng 4, 0 hàng 2 và 1 hàng 1: 8+4+0+1 = 13 (1111 là 15)

Toán từ lô-gic (AND/OR/NOT/XOR) trong VBA là toán tử tính theo bit.
NOT lật ngược tất cả các bít trong con số.
AND so sánh các bít của hai vế. Từng đơn vị (nhị phân) tương ứng nhau.

1649665912226.png
> -1 là số có tất cả các bít là 1. 0 là số có tất cả các bít là 0.
> vì vậy, khi Not lật ngược tất cả các bít thì -1 thành 0 và 0 thành -1. Lưu ý rẳng 1 lật ngược thành -2.

1649666060387.png
> 1 có bit đầu tiên (hàng 1) là 1, còn lại là 0's. 2 chỉ có bit thứ nhì là 1, còn lại là 0's. Vì vậy, khi [bit] And thì hai thằng chả khớp nhau, kết quả là 0 (tất cả các bít là 0).
> nhưng 2 (01) và 3 (11) thì cùng có bít thứ nhì là 1 (xin xem chỉnh sửa ở cuối bài). Khi mang ra And thì 2 thằng chỉ khớp nhau bit thứ nhì, các bít còn lại là 0's. Kết quả là số 2.

1649667685550.png
> hình trên dễ hiểu, không cần giải thích

Trở về việc tính chẵn lẻ (chỉ tính số dương và 0). Ta biết rằng:
- trong TẤT CẢ máy tính số chẵn có bít thứ nhất là 0 và số lẻ có bit này là 1.
- toán tử xét bit là một trong những toán tử tự nhiên của CPU. Vì vậy nó rất nhanh, rất ít năng lượng.

Vì vậy đem xét số chẵn lẻ bằng cách xét bit thứ nhất của nó là cách hiệu quả nhất.

Chú thích thêm:
Trong bảng mã ASCII, A-Z chỉ khác a-z bằng bít thứ 6 (số 32). Vì vậy, ngày xưa các phép tính LCase A-Z chỉ cần +32 hay Or 32 ký tự. Ngược lại để UCase A-Z thì -32.
Tuy nhiên, qua thập niên 80's thì Mẽo chấp nhận rằng hế giới không phải chỉ mình ta, và nhìn nhận bảng mã mở rộng Unicode. Việc xét bít 32 không còn giản dị như xưa nữa.

Chỉnh bài: theo đúng như nhận xét của bạn ở bài #18. Toi xin chỉnh lại: số 2 là 10 chứ không phải 01.
1649690754404.png
 
Lần chỉnh sửa cuối:
toán tử xét bit là một trong những toán tử tự nhiên của CPU. Vì vậy nó rất nhanh, rất ít năng lượng.

Vì vậy đem xét số chẵn lẻ bằng cách xét bit thứ nhất của nó là cách hiệu quả nhất.
Cái này không cần bàn cãi vì nó đúng. Nhưng theo tôi vấn đề nằm ở chỗ mức độ hiệu quả hơn nhiều hay rất rất nhiều so với các phương pháp khác. Thực ra nếu ta không viết code để thực hiện 1000 lần trong 1 giây, hàng trăm lần trong 8 tiếng làm việc thì quên AND đi. Sự chênh lệch so với MOD chỉ ở mức cho các bác học đàm đạo với nhau trên bàn nhậu thôi.

Trong cuộc sống, trong thực tế, đôi khi người ta lựa chọn giữa 2 phương pháp A và B không vì tiêu chí nhanh chậm khi A nhanh hơn B nhưng không đáng kể. Vd. với code để chạy thỉnh thoảng 1 lần và là code viết cho người khác, rất có thể họ có trình độ bình thường, thì nên dùng MOD. MOD theo tôi dễ hiểu với người bình thường hơn rất nhiều. Tuy nhiên nếu tôi viết code để chạy liên tục, hàng nghìn lần trong 1 giây thì tôi lại dùng AND. Trong cuộc sống sự lựa chọn tùy thuộc vào từng hoàn cảnh. Không phải lúc nào người ta cũng chọn AND thay cho MOD đâu. Cũng như viết code. Nhiều khi có thể viết code rất phức tạp và dài dòng để tốc độ chạy nhanh chóng mặt, thậm chí dùng thư viện ngoài. Nhưng nhiều khi người ta chọn code chậm hơn một chút để đánh đổi lại có code đơn giản hơn, dễ hiểu hơn, dễ bảo trì hơn. Code càng đơn giản thì cơ hội phạm lỗi càng ít.

Đây chỉ là ý kiến chủ quan thôi.
 
Quả thật là từ hồi biết dùng máy tính đến giờ tôi mới biết chuyện And so sánh bit như bài #10 phân tích. Thật ngạc nhiên vì với tôi, And chỉ là phép "Và" như hồi nào đến giờ của chương tập hợp và ánh xạ của môn toán đại số lớp 10, rồi được đem vào làm thành 1 toán tử của tin học.

Và (And) tôi rất tán thành những gì nêu tại bài #12. Bây chừ máy tính cá nhân đã mạnh còn hơn máy chủ những năm 90 nên có lẽ nhanh hơn tí chưa chắc đã hơn sự tiện lợi, dễ làm.

Không biết And 2 đoạn trên của tôi có kết quả là mấy không biết --=0
 
Cái này không cần bàn cãi vì nó đúng. Nhưng theo tôi vấn đề nằm ở chỗ mức độ hiệu quả hơn nhiều hay rất rất nhiều so với các phương pháp khác. Thực ra nếu ta không viết code để thực hiện 1000 lần trong 1 giây, hàng trăm lần trong 8 tiếng làm việc thì quên AND đi. Sự chênh lệch so với MOD chỉ ở mức cho các bác học đàm đạo với nhau trên bàn nhậu thôi.

Trong cuộc sống, trong thực tế, đôi khi người ta lựa chọn giữa 2 phương pháp A và B không vì tiêu chí nhanh chậm khi A nhanh hơn B nhưng không đáng kể. Vd. với code để chạy thỉnh thoảng 1 lần và là code viết cho người khác, rất có thể họ có trình độ bình thường, thì nên dùng MOD. MOD theo tôi dễ hiểu với người bình thường hơn rất nhiều. Tuy nhiên nếu tôi viết code để chạy liên tục, hàng nghìn lần trong 1 giây thì tôi lại dùng AND. Trong cuộc sống sự lựa chọn tùy thuộc vào từng hoàn cảnh. Không phải lúc nào người ta cũng chọn AND thay cho MOD đâu. Cũng như viết code. Nhiều khi có thể viết code rất phức tạp và dài dòng để tốc độ chạy nhanh chóng mặt, thậm chí dùng thư viện ngoài. Nhưng nhiều khi người ta chọn code chậm hơn một chút để đánh đổi lại có code đơn giản hơn, dễ hiểu hơn, dễ bảo trì hơn. Code càng đơn giản thì cơ hội phạm lỗi càng ít.

Đây chỉ là ý kiến chủ quan thôi.
Tôi không thuộc trường phái "tiết kiệm từng phần ngàn giây".
Lúc tôi giới thiệu cái vụ And này thì tôi có nói rằng nó cần biết khi trình độ đã vượt trên mức căn bản.

Vả lại, tôi vẫn quan niệm toán tửu Mod chẳng phải là căn bản. Mod 2 thì cũng khó hiểu chả kém gì And 1, chỉ bà con không nắm vững And cho nên không có tự tin với nó thôi.

Tuy nhiên, tôi không cố chấp, nếu bà con tin Mod 2 dễ hiểu thì tôi không cãi thêm. Rừng nào cọp nấy. Nhập giang tuỳ khúc, nhập gia tuỳ tục.
 
Quả thật là từ hồi biết dùng máy tính đến giờ tôi mới biết chuyện And so sánh bit như bài #10 phân tích. Thật ngạc nhiên vì với tôi, And chỉ là phép "Và" như hồi nào đến giờ của chương tập hợp và ánh xạ của môn toán đại số lớp 10, rồi được đem vào làm thành 1 toán tử của tin học.

Và (And) tôi rất tán thành những gì nêu tại bài #12. Bây chừ máy tính cá nhân đã mạnh còn hơn máy chủ những năm 90 nên có lẽ nhanh hơn tí chưa chắc đã hơn sự tiện lợi, dễ làm.

Không biết And 2 đoạn trên của tôi có kết quả là mấy không biết --=0
Chính vì tôi biết có rất nhiều người như bạn nên tôi viết trong bài #11
MOD theo tôi dễ hiểu với người bình thường hơn rất nhiều.

Bạn không biết ... vì bạn và nhiều người ít đọc help. Tôi biết là có nhiều người từng viết nhiều trong Delphi nhưng có những cái không biết vì không chịu khó đọc help. Tôi ngay từ những năm cuối 90 của thế kỷ trước, khi mới bắt đầu lập trình trong Delphi 5 tôi đã biết vì đọc help.
Trong Delphi 5 có NOT, AND, OR và XOR thao tác trên các giá trị Boolean và trả về kết quả là các giá trị Boolean. Đây là operator mà bạn biết. Nhưng trong Delphi 5 cũng có NOT, AND, OR, XOR, SHL và SHR thao tác trên từng bit của giá trị Integer (Integer trong Delphi 5 là 32 bit) và trả về kết quả Integer. Đây là AND ... mà bác VetMini đang nói tới.

Nhiều người cũng từng viết không chỉ 1 code trong Delphi nhưng họ không biết là trong Delphi có AND này và AND kia đâu. Vì thế mà tôi nói là MOD (operator số học) dễ hiểu hơn AND (bitwise) - thao tác trên từng bit.

delphi1.JPG

delphi2.JPG
 
Quả thật là từ hồi biết dùng máy tính đến giờ tôi mới biết chuyện And so sánh bit như bài #10 phân tích. Thật ngạc nhiên vì với tôi, And chỉ là phép "Và" như hồi nào đến giờ của chương tập hợp và ánh xạ của môn toán đại số lớp 10, rồi được đem vào làm thành 1 toán tử của tin học.

Và (And) tôi rất tán thành những gì nêu tại bài #12. Bây chừ máy tính cá nhân đã mạnh còn hơn máy chủ những năm 90 nên có lẽ nhanh hơn tí chưa chắc đã hơn sự tiện lợi, dễ làm.

Không biết And 2 đoạn trên của tôi có kết quả là mấy không biết --=0
1. Bạn đọc không kỹ giải thích của tôi.
Toán tử And không phải ngôn ngữ nào cũng vậy. VBA chỉ là một ngôn ngữ thuộc nhóm dùng And là bit and. Và hai vế trái phải của And là số nguyên.
Có những ngôn ngữ bắt buộc hai vế phải là Boolean. Nếu vế nào có trị khác Boolean thì sẽ bị ép kiểu. Lúc ấy chúng tính lô gic thẳng True/Fasle, không dùng bít.
Có những ngôn ngữ phân biệt Boolean-And và bit-And. Điển hình là các ngôn ngữ dòng họ C như JavaScript (Google Scirpt gần như in hệt JavaScript) dùng && cho Boolean-And và & cho bit-And.

2. Tôi không nhớ nổi xét bit 2 của một số là con toán gì. Bit 1 là số chẵn lẻ, bit cuối cùng là âm/dương.
Chỉ biết là lấy bit của đoạn văn thì là cách dùng nguy hiểm. Dân chơi chính trị rất khoái trò này vì nó là một nghệ thuật lấy lời của người ta ra khỏi ngữ cảnh của nó, với mục đích diễn theo nghĩa khác.
(tiếng Anh, bit là một phần, tiếng IT, bit là viết tắt binary digit)

3. Chú thêm: cách xưa, người ta hay chèn các thông số 1/0 (True/False) vào các bít của một số.
Điển hình, thay vì phải nạp hàm
Func1(a1 as Boolean, a2 As Boolean, a3 As Boolean)
If a1 Then ...
If a2 Than ...
If a3 Then ...
End Function

Func2(aChung As Integer)
If (aChung And 1) Then...
If (aChung And 2) Then...
If (aChung And 4) Then...
End If

Code Gọi:
Sub t()

Func1(True, False, True) ---- hoặc Func1(1, 0, 1)
Func2(5) ---- hoặc a = 1: a = a + 4 (hay a And 4): Func2(a)
End Sub

Ngày xưa, kỹ thuật dùng bit nằm trong phần mở rộng của căn bản lập trình. Bây giờ thì máy tính chạy nhanh, hiểu biết về bít không còn thật quan trọng nữa cho nên nó nằm trong phần nâng cao.
Bạn nào học qua phần nâmg cao, chắc sẽ có học qua cái gọi là enum. Enum dùng để xét bit rất hiệu quả.

Chỉnh sửa: ở trên, trước đây tôi gõ lầm | là toán tử bit-and. Không đúng, tôi sửa lại & là toán tử bit-and. ( | là bit Or )
 
Lần chỉnh sửa cuối:
THì giải thích:

Nên nhớ, bên trong máy thì các số được diễn đạt bằng hệ nhị phân, điển hình Integer có 16 bít, Long có 32 bít.
Khái niệm các hàng đơn vị:
- hệ thập phan có hàng đơn vị, hàng chục, hàng trăm,... Điển hình hàng chục là chữ số thứ 2 đếm từ bên phải.
Con số 123 là 1 hàng trăm, 2 hàng chục, 3 3 hàng đơn vị.
- hệ nhị phân có hàng 1, hàng 2, 4, 8, ... Điển hình hàng 4 là bit thứ 3 đếm từ nên phải.
Con số 1101 là 1 hàng 8, 1 hàng 4, 0 hàng 2 và 1 hàng 1: 8+4+0+1 = 13 (1111 là 15)

Toán từ lô-gic (AND/OR/NOT/XOR) trong VBA là toán tử tính theo bit.
NOT lật ngược tất cả các bít trong con số.
AND so sánh các bít của hai vế. Từng đơn vị (nhị phân) tương ứng nhau.

View attachment 274287
> -1 là số có tất cả các bít là 1. 0 là số có tất cả các bít là 0.
> vì vậy, khi Not lật ngược tất cả các bít thì -1 thành 0 và 0 thành -1. Lưu ý rẳng 1 lật ngược thành -2.

View attachment 274288
> 1 có bit đầu tiên (hàng 1) là 1, còn lại là 0's. 2 chỉ có bit thứ nhì là 1, còn lại là 0's. Vì vậy, khi [bit] And thì hai thằng chả khớp nhau, kết quả là 0 (tất cả các bít là 0).
> nhưng 2 (01) và 3 (11) thì cùng có bít thứ nhì là 1. Khi mang ra And thì 2 thằng chỉ khớp nhau bit thứ nhì, các bít còn lại là 0's. Kết quả là số 2.

View attachment 274289
> hình trên dễ hiểu, không cần giải thích

Trở về việc tính chẵn lẻ (chỉ tính số dương và 0). Ta biết rằng:
- trong TẤT CẢ máy tính số chẵn có bít thứ nhất là 0 và số lẻ có bit này là 1.
- toán tử xét bit là một trong những toán tử tự nhiên của CPU. Vì vậy nó rất nhanh, rất ít năng lượng.

Vì vậy đem xét số chẵn lẻ bằng cách xét bit thứ nhất của nó là cách hiệu quả nhất.

Chú thích thêm:
Trong bảng mã ASCII, A-Z chỉ khác a-z bằng bít thứ 6 (số 32). Vì vậy, ngày xưa các phép tính LCase A-Z chỉ cần +32 hay Or 32 ký tự. Ngược lại để UCase A-Z thì -32.
Tuy nhiên, qua thập niên 80's thì Mẽo chấp nhận rằng hế giới không phải chỉ mình ta, và nhìn nhận bảng mã mở rộng Unicode. Việc xét bít 32 không còn giản dị như xưa nữa.
Bài viết rất hay thiết thực và dể hiểu, nếu được bạn phát triển rộng ra thành chuyên đề về các toán tử logic để mọi người nâng cao tư duy lập trình, nhiều người tuy đọc help về các toán tử logic nhưng chưa dám dùng vì chưa hiểu tường tận, trên GPE rất hiếm sử dụng toán logic
Ghi chú: "nhưng 2 (01) và 3 (11) " bạn gỏ nhầm (10) thành (01)
 
...
Nhiều người cũng từng viết không chỉ 1 code trong Delphi nhưng họ không biết là trong Delphi có AND này và AND kia đâu. Vì thế mà tôi nói là MOD (operator số học) dễ hiểu hơn AND (bitwise) - thao tác trên từng bit.
...
Delphi là nền tảng lập trình hướng đối tượng.
Những người bác nói ấy có thể biết xử dụng loại lập trình này nhưng chưa chắc đã nắm vững.

Đối với LTHĐT, phải coi chừng toán tử có thể được viết theo kiểu hàm chồng (*1) (cả code lẫn compiler). Tức là cách hoạt động của nó có thể tuỳ thuộc vào kiểu của tham số truyển cho nó (hai vế hai bên) (*2).
Theo như lời của bác thì tôi suy diễn (educated guess, không có nghĩa là bảo đảm 100%) Delphi rất có thể theo tinh thần này. Và đúng như bác nói, dùng nó thì phải đọc tài liệu của chính chủ xem với mỗi kiểu tham số nó sẽ làm việc thế nào, nếu hai vế khác kiểu thì kiểu nào sẽ lấn kiểu nào (bên nào bị ép kiểu). (*3)

(*1) Hàm chồng: nhiều hàm cùng một tên, mỗi hàm dùng một chữ ký riêng để compiler biết nó phải móc vào hàm nào (*6). Thường thì chữ ký của hàm được hiểu là số lượng, và/hoặc kiểu của tham số truyền vào. Hầu hết các ngôn ngữ LTHĐT đều chấp nhận hàm chồng, trừ các ngôn ngữ coi tất cả các biến là Var như JavaScript. (*4)

(*2) Theo nguyên tắc hàm chồng thì rất có thể (lại educated gues) bên trong nền tảng Delphi, And được diễn giải rằng:
(Bool) And (Bool) --> 1 loại chữ ký --> compiler gọi code dịch And là toán tử lôgic thuần tuý.
(Int) And (Int) --> loại chữ ký thứ hai --> compiler gọi code dịch And là toán tử xét bit.
vân vân

(*3) Như trên, compiler rất có thể phải ép kiểu 1 vế hoặc cả hai vế để thực hiện việc dịch toán tử. (vì vậy ở tren tôi đặt tên kiểu trong dấu ngoặc, ngụ ý là sau khi ép kiểu.

(*4) VBA dùng variant, optional, và parramarray để cho hàm chấp nhận nhiều con số tham khác nhau. Nhưng đó là việc run time, tức lúc chạy code. Ở đây, ta nói về lúc compile code.

(*5) Một số người cho hàm chồng là 1 trong những phép đa hình. Tôi không hẳn đồng ý. Vì hàm chồng chỉ là cái tên dùng lại, được compiler băm ra và kết nối từ lúc compile. Đa hình ở cấp cao là kết nối lúc run time. Lớp (class) là dạng virtual (ảo), và chứa một số hàm dạng ảo. Lúc chạy, nền tảng mới lục bảng ảo (virtual table) ra để biết kiểu của đối tượng hoặc chữ ký của hàm - kết nối trễ.
Kiểu như ở VBA bạn dùng:
Dim dt As Object, tenKieu As String
tenKieu = "Scripting.Dictionary"
Set dt = CreateObjcet(tenKieu)
Ở đây, dt có thể coi là đa hình. Tuỳ theo trị của tenKieu là gì mà nó là cái gì.

(*6) Móc hàm có nghĩa là complier đưa địa chỉ của code hàm vào chỗ đó. Một số ngôn ngữ cho phép chọn đưa thẳng code cuả hàm vào thay thế chỗ gọi hàm (từ khoá #define trong C, và inline trong C++, Lambda trong Excel, JavaScript thì quá tự nhiên). Với VBA thì tôi không biết nó có tuỳ tiện inline mấy hàm nhỏ quá hay không, nhưng tôi biết có một số phiên bản Basic thì làm vậy để tăng tốc code (inline làm phồng code lên, nhưng không quan trọng với hàm nhỏ.
Các toán tử căn bản như +- thì có lệnh máy trực tiếp của CPU, hơi khó chút như */ thì có thể đẩy qua ALU (nếu có). Nhưng toán tử phức tạp hơn nữa như MOD thì có lẽ VBA có sẵn một đoạn code, khi biểu thức dùng thì compiler lôi ra nhét vào chỗ đó.
 
Lần chỉnh sửa cuối:
Theo như lời của bác thì tôi suy diễn (educated guess, không có nghĩa là bảo đảm 100%) Delphi rất có thể theo tinh thần này. Và đúng như bác nói, dùng nó thì phải đọc tài liệu của chính chủ xem với mỗi kiểu tham số nó sẽ làm việc thế nào, nếu hai vế khác kiểu thì kiểu nào sẽ lấn kiểu nào (bên nào bị ép kiểu). (*3)
...
(*3) Như trên, compiler rất có thể phải ép kiểu 1 vế hoặc cả hai vế để thực hiện việc dịch toán tử. (vì vậy ở tren tôi đặt tên kiểu trong dấu ngoặc, ngụ ý là sau khi ép kiểu.
Như trong hình khi chạy bất cứ dòng nào trong 4 dòng cuối thì đều có lỗi "Operator not applicable to this operand type"

and.JPG

Tức không có chuyện 1 tham số integer còn tham số kia là boolean. Chỉ chấp nhận hoặc 2 boolean hoặc 2 integer.

Tóm lại trong trường hợp trên compiler không "ngầm ngầm" ép kiểu. Nếu muốn thì người viết code phải tự ép kiểu - tường minh.

a = True, b = False thi Integer(a) = 1, Integer(b) = 0

Nhưng ép integer về boolean thì phải cẩn thận. Khi chạy code trong hình dưới

vdthu2.JPG

Thì thấy chỉ có cửa sổ thứ 3 hiển thị số 1. Tại sao? 4000 (dec) = 0FA0 (hex). Do kiểu boolean có 1 BYTE nên boolean(4000) = boolean(0FA0) = A0 (hex) = 160. Tức khi ép thì chỉ lấy 1 BYTE. Tương tự boolean(2) = 2, boolean(1) = 1. Mà "a = true" chỉ thỏa khi a = 1.

Nếu thay cả 3 điều kiện "a = true" bằng "a = false" thì không có cửa sổ nào được hiện. Chỉ khi " a := boolean(0)" thì cửa sổ mới hiện với con số 0.

Nhưng nếu thay bằng "If a then" - có nghĩa không là "a = true", và không là "a = false" thì cả 3 cửa sổ đều hiện với 3 con số 160 (a = 160), 2 (a = 2), 1 (a = 1)

Tóm lại a: boolean là kiểu 1 BYTE. Nếu có a = false thì trong a có giá trị 0, nếu a = true thì trong a có giá trị 1. Nhưng nếu có a = boolean(c) với c là integer thì trong a có thể có giá trị tới 255 (nằm trong giới hạn 1 BYTE).

Cùng 1 code với cùng 3 giá trị nhưng với If a = true then thì chỉ có cửa sổ cuối với a = 1, với If a = false then thì không có cửa sổ nào, còn với If a then thì có cả 3 cửa sổ.
 
Web KT

Bài viết mới nhất

Back
Top Bottom