Biến integer & biến long cái nào nhanh hơn?

  • Thread starter Thread starter digita
  • Ngày gửi Ngày gửi
Liên hệ QC
D

digita

Guest
Tối nay rãnh rổi tôi làm thữ 1 thí nghiệm nho nhỏ và rất ngạc nhiên khi thấy kết quả. Muốn vào trong link http://www.giaiphapexcel.com/forum/showthread.php?t=13195&page=2 đóng góp ý kiến thì thấy nó bị khóa. Đọc kỹ các bài thì tôi đoán được lý do. Dù sao, tôi cũng khám phá 1 cái lạ và muốn chia sẽ với các anh chị em trong GPE.

Các bạn chạy code sau rồi sẽ thấy câu trả lời nhá.

Mã:
Sub BenchMark()
Dim VInt1 As Integer, VInt2 As Integer, VInt3 As Integer
Dim VLong1 As Long, VLong2 As Long, VLong3 As Long
Dim BMInt As Double, BMLong As Double

BMInt = Timer

For VInt1 = 1 To 254
  For VInt2 = 1 To 254
     VInt3 = (VInt1 + VInt2) / VInt1 ^ 2
  Next
Next
BMInt = Timer - BMInt

BMLong = Timer
For VLong1 = 1 To 254
  For VLong2 = 1 To 254
      VLong3 = (VLong1 + VLong2) / VLong1 ^ 2
  Next
Next
BMLong = Timer - BMLong
MsgBox "Dim Integer time = " & Format(BMInt, "#.####0") &  " secs" & vbNewLine & _
           " Dim Long time = " & Format(BMLong, "#.####0") & " secs"

End Sub

Ndu ơi,

Rất khâm phục cách đối xử của bạn. Tuy nhiên, như mình nói với bạn trước đây mình dám nhận danh xưng thầy hay cao thũ vì mình không phải là thầy giáo và luôn luôn biết giới hạn sự hiểu biết của mình. Tôi chỉ muốn là người đồng hành tham gia và học hòi thêm từ bạn và các thành viên khác trong diễn đàn này. Vậy xin bạn đừng gọi tôi là thầy nữa nha.

Kiến thức, theo thiển ý tôi, là 1 phần của nhân phẩm. Mà là con người không ai hoàn thiện hết. Đọc qua câu văn cách hành văn thì có thể biết nhân cách và ẩn ý của người viết.

Chúc mọi người 1 cuối tuần an lành.
 
Nguyên văn bởi hai2hai
Có thể dùng các công cụ của Numega (Softice, Smartcheck, DevPartner), hay AQTime,... để debug xem ứng dụng chạy thì nó làm những gì (không phải debug bình thường kiểu ta hay làm đâu)
Đọc bài hướng dẫn, mình rất nể phục kiến thức sâu rộng của bạn. Tuy nhiên, lời chỉ dẫn của bạn đã vượt quá xa trình độ của mình. Nếu như có thể đọc tài liệu tiếng Anh theo mấy đường dẫn ấy, có thể dùng các công cụ debug ấy thì mình đâu cần bạn giúp đỡ. Điều mình yêu cầu cũng đơn giản thôi, mong ở bạn sự trợ giúp trực tiếp, cụ thể.
1. Các bạn cho rằng khi VB6 compiled sang mã máy thì nó sẽ convert những biến dạng Byte, Integer sang kiểu Long. Thế thì lệnh convert này được thực thi khi VB6 compiled sang mã máy chứ đâu phải trong giai đoạn Runtime. Từ đó suy ra, sau khi biên dịch sang mã máy rồi , dù khai báo kiểu gì: Integer hay Long
các chương trình sẽ chạy giống nhau.
2. Trong VBA, có compiled sang mã máy không? Lệnh convert được thực thi lúc nào?
3.
Integer trong VB6, VBA thì là 16 bits, signed, nhưng khi dịch sang mã máy thì vẫn thừa 2 bytes trên thanh ghi (4 bytes) (đối với 32-bit processor). Còn khi tính toán thì vẫn sử dụng 16 bits chứ ko phải 32 bits.
-Nếu Interger (16 bits) biên dịch sang mã máy thừa 2 bytes và tính toán vẫn sử dụng 16 bits có nghĩa là nó vẫn là Integer, chưa convert thành Long. ( Điều mình muốn hỏi là sau khi convert thành Long rồi, sao còn bị báo lỗi Overflow?)
4. VẤN ĐỀ TẾ NHỊ: Đặt câu hỏi thêm thế này, mình rất ngại vì sợ làm phiền các bạn. Nếu các bạn không có thời gian trợ giúp thì topic này có thể đóng tại đây. (Xin lỗi digita nhé!)
 
Upvote 0
Các bạn xem thủ tục đơn giản này:
Mã:
Sub MyByte()
Dim b1 As Byte, b2 As Byte, i As Long
For b1 = 1 To 200
  For b2 = 1 To 200
    i = b1 + b2
  Next
Next
End Sub
Mặc dầu khai báo i là Long nhưng chạy đến i=255 thì báo lỗi.
Nhưng khai báo lại b1, b2 là Interge hay Long thì chạy tốt ?
 
Upvote 0
Mr Okebab đã viết:
Đối với em (cá nhân): Thay vì thời gian bỏ ra để tìm hiểu xem tại sao Bill lại không làm như ta nghĩ thì để tìm hiểu về cái khác sẽ có ích hơn. (Giống như cứ tìm hiểu mãi về cái vụ tại sao trong VBA True = -1??) Thân!
Đúng vậy BAB à; đối với người này, khi này lấy vợ quan trọng, nhưng với người kia, bỏ vợ là mục tiêu quan trọng hàng đầu trong thời điểm này thì sao!
Cho nên trên đây, chúng ta không nên khuyên, rằng hãy ngưng ngay đi các bạn;
Mà chỉ nên nói: "Ai muốn tiếp tục thì cứ việc!" - Cũng là 1 câu nói!
Thứ đến
Những người tự học như bọn này, trong kiến thức còn rất nhiều ổ voi; Mà có khi do thói quen xấu lại không muốn sửa;
Riêng việc khai báo kiểu biến mà các bạn đề cập; Dù rằng biết mười mươi là nên khai báo As Long để tăng tốc, để chứng tỏ ta đây hiểu biết hơn (!) nhưng do thói quen rằng nên quản lý biến trong khuôn khổ, nên trong chương trình cứ khai đủ kiểu vậy đó; Có ai hỏi thì, rằng là để quản lý biến! Thế thôi!
Thế có điên khùng & bảo thủ không kia chứ!
Rất mong đừng cười cho sự cổ hữu & kém hiểu biết của mấy anh Nông dân làm VBA này, nha. Tội nghiệp!
 
Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
Các bạn xem thủ tục đơn giản này:
Mã:
Sub MyByte()
Dim b1 As Byte, b2 As Byte, i As Long
For b1 = 1 To 200
  For b2 = 1 To 200
    i = b1 + b2
  Next
Next
End Sub
Mặc dầu khai báo i là Long nhưng chạy đến i=255 thì báo lỗi.
Nhưng khai báo lại b1, b2 là Interge hay Long thì chạy tốt ?

Em nghĩ lời giải thích trong phần trả lời số 5 của hai2hai.

Lê Văn Duyệt
 
Upvote 0
1. Các bạn cho rằng khi VB6 compiled sang mã máy thì nó sẽ convert những biến dạng Byte, Integer sang kiểu Long. Thế thì lệnh convert này được thực thi khi VB6 compiled sang mã máy chứ đâu phải trong giai đoạn Runtime. Từ đó suy ra, sau khi biên dịch sang mã máy rồi , dù khai báo kiểu gì: Integer hay Long
các chương trình sẽ chạy giống nhau.
2. Trong VBA, có compiled sang mã máy không? Lệnh convert được thực thi lúc nào?

@voda: Anh dùng Numega Softice đi, rồi sẽ hiểu. Interpreting, Compiling (gọi là thông dịch và biên dịch, lúc chạy chương trình thì nó thực hiện cái chuyện dịch đó từ cái mớ loằng ngoằng binary code sang số 0, số 1 để cho cái cục sắt đáng ghét mà ko thể bỏ được của chúng ta hiểu) được thực hiện khi runtime chứ ko phải lúc dịch (compiled) ra file exe dạng mã máy :) (anh view file exe lên xem có phải là số 0, số 1 ko? :), làm sao máy nó hiểu được cái mớ loằng ngoằng đó khi chạy?). Mà anh có biết khi anh viết VBA thì "phần mềm" của anh là cái gì ko? Không phải là file xls đâu nhé, là cái Excel.exe ấy. Còn viết trên VB thì có 2 chế độ dịch, trong đó có 1 cách dịch thẳng sang binary code (mặc địch dịch theo cách này, và khi đó nó mới là 1 ứng dụng thực sự độc lập theo nghĩa biên dịch), còn 1 cách thì vẫn thông qua VB lúc chạy.

Anh tưởng tượng thế này: Khi anh chạy SoftIce, nó sẽ chạy dưới nền của Windows. Lúc anh chạy bất cứ 1 ứng dụng gì, anh sẽ nhìn thấy phần địa chỉ của từng procedure (function trong ASM cũng được gọi là proc) và nhìn thấy từng biến nó lưu trong các thanh ghi dữ liệu thế nào.

Nhắc lại: "Dịch" ở đây có 2 nghĩa (vì thế có thể làm cho anh voda hiểu nhầm và thắc mắc): Dịch từ Sourcecode ra mã máy dạng Binary (cái này ngôn ngữ lập trình thực hiện, còn VBA thì ko có dịch vì bản chất nó là file Excel nó tự hiểu ngôn ngữ VBA, vì thế mới ko nói các xls trên Excel là "phần mềm" mà phải sửa hết là "file xls documents do Excel quản lý"). Sau khi chạy cái mớ Binary đó thì nó phải Interpret & Compile sang 0 & 1 để cục sắt hiểu (dĩ nhiên là thông qua hệ điều hành nữa. Mình đang chạy trên môi trường ứng dụng 32-bit processor). PC cũng phải hiểu mấy cái thư viện APIs của Windows thành số 0, số 1 hết. Còn khi chạy ứng dụng .NET thì lại thông qua 1 ông nữa, là ông .NET Framework ấy.

Nhân tiện đây nói luôn: Tại sao "chúng nó" cr*ck được ra cái Serial, tạo cái K*ygen?
Bởi "chúng nó" xem được mọi hành động trên ứng dụng đó theo cách trên. Nó sẽ biết được địa chỉ của từng proc 1 (nhất là cái thủ tục SN validation ấy (dùng phối hợp với các phần mềm dịch ngược ASM như DASM,...)), và view được giá trị của từng thanh ghi (trong đó có cái biến chưa SN được lưu). Cái K*ygen thì làm phức tạp hơn.

Và cũng chỉ giải thích đến đây được thôi. :)

Mọi người cứ tiếp tục trao đổi nếu chưa thỏa đáng (có thể sẽ có nhiều người khác tham gia trả lời), hai2hai xin tạm dừng (không trả lời trực tiếp trên diễn đàn cho người hỏi về vấn đề này hoặc liên quan tới cr*).
 
Lần chỉnh sửa cuối:
Upvote 0
Nguyên văn bởi phamduylong
Các bạn xem thủ tục đơn giản này:
Mã:
Sub MyByte()
Dim b1 As Byte, b2 As Byte, i As Long
For b1 = 1 To 200
  For b2 = 1 To 200
    i = b1 + b2
  Next
Next
End Sub
Mặc dầu khai báo i là Long nhưng chạy đến i=255 thì báo lỗi.
Nhưng khai báo lại b1, b2 là Interge hay Long thì chạy tốt ?
Các bạn xem dùm tại sao viết thế này, code lại chạy bình thường:
Mã:
Sub MyByte()
Dim b1 As Byte, b2 As Byte, i As Long
For b1 = 1 To 200
  For b2 = 1 To 200
    i = 0 + b1 + b2
  Next
Next
End Sub
 
Upvote 0
Để lý giải tại sao, mọi người chỉ cần test: (Không sử dụng đến biến i AS Long)

Mã:
Sub MyByte()
Dim b1 As Byte, b2 As Byte, i As Long
For b1 = 1 To 200
  For b2 = 1 To 200
    If b1 + b2 = 255 Then
       MsgBox b1 + b2
    End If
  Next
Next
End Sub

Trong lúc thực hiện, giá trị trở về của b1 + b2 có kiểu lớn nhất của 1 trong 2 biến có trong biểu thức (nếu 2 biến đó có kiểu byte thì giá trị trở về có kiểu byte ==> tràn số). Nếu thêm số 0 ở đầu, giá trị trở về đó sẽ có kiểu khác và khi đó ko bị tràn số nữa.

Khi biên dịch lúc chạy (compiling) thì nó ko tính toán như ta tính nhẩm đâu. b1 + b2 sẽ lưu vào 1 "biến" khác (gọi là kết quả), có kiểu như đã giải thích ở trên. Sau đó nó mới gán vào biến i. Nhưng ở trường hợp trên, chưa kịp gán vào i đã ...overflow (b1 + b2 có kiểu byte sẽ bị overflow) rồi. Giờ thử tiếp: Khai báo biến b1 kiểu Integer, b2 kiểu byte rồi mọi người sẽ thấy.

Đây thì đúng là vấn đề cơ bản của chương trình dịch rồi. Đúng là ngày xưa bọn tôi có học môn này :)


:)
 
Upvote 0
Nói tóm lại khi chạy code để phân tích dữ liệu nhỏ thì khai báo biến long hay integer thì không thấy nhanh chậm bao nhiêu.

Nhưng khi làm việc với 1 bảng dữ liệu lớn tử vài chục ngàn record thì biến long nó làm code chạy nhanh hơn rất nhiều.

from hai2hai:
Sau một hồi, bạn vẫn chưa đúc kết ra 1 kết luận mà mình muốn nói xuyên suốt quá trình thảo luận. Kết luận là: NÊN (hãy tạo thói quen) sử dụng Long thay cho Integer trong hầu hết các trường hợp (Kể cả dữ liệu nhiều hay ít). Và tham khảo khi nào thì dùng Integer ở bài của hai2hai ở trên.
 
Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
Web KT

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

Back
Top Bottom