cz910021
|
分享:
▲
▼
更新後
Dim x, y, a As String, i, j As Integer : x = TextBox1.Text : y = TextBox2.Text Dim t As Boolean = False : a = 0 If x > y Then MsgBox("起始值需小於結束值", , "題示") End If
If x <> Fix(x) Then MsgBox("請輸入整數", , "題示") TextBox1.Focus() TextBox1.SelectAll() Exit Sub ElseIf (y <> Fix(y)) Then MsgBox("請輸入整數", , "題示") TextBox2.Focus() TextBox2.SelectAll() Exit Sub End If
For i = x To y If i Mod 3 = 0 Or InStr(i, 3) <> 0 Then t = True Else t = False End If
If Not (t) Then a += Val(i) End If Next TextBox3.Text = a End Sub
|
|
x0
[1 樓]
From:IANA | Posted:2013-09-15 17:19 |
|
|
ebolaman
級別: 副版主
版區: 程式設計
x38
x458
|
分享:
▲
我用 VB.NET 來寫,要轉成 VB6 應該不困難 第一種優化 (Calc2): 因為 3, 6, 9, 12, 15... 3 的倍數被排除掉 因此只要把剩下的 (3n-1), (3n-2) 再排除掉 含有 3 的數字加起來,結果一樣 這樣子 1/3 的運算就被省下來了 第二種優化 (Calc3): 排除掉數字含有 3 除了先轉字串再找有沒有 3 也可以每次除以10, 看 Mod 10 是否等於 3 因為轉換通常比較花時間,用純數學的方式也可以省下不少時間 複製程式
Imports System.ComponentModel
Public Class Form1
Private Structure TestsInfo
Public ReadOnly start As Long
Public ReadOnly last As Long
Public ReadOnly expected As Long
Public Sub New(ByVal start As Long,
ByVal last As Long,
ByVal expected As Long)
Me.start = start
Me.last = last
Me.expected = expected
End Sub
End Structure
Private Class BenchmarkResult
Private m_index As Integer
Private m_name As String
Private m_ms As Double
Private m_perf As Double
Public Sub New(ByVal index As Integer,
ByVal name As String,
ByVal ms As Double)
m_index = index
m_name = name
m_ms = ms
End Sub
Public Sub CalcPerf(ByVal avgElapsed As Double)
m_perf = avgElapsed / m_ms
End Sub
Public Property Index As Integer
Get
Return m_index
End Get
Set(ByVal value As Integer)
m_index = value
End Set
End Property
Public Property Name As String
Get
Return m_name
End Get
Set(ByVal value As String)
m_name = value
End Set
End Property
Public Property Ms As Double
Get
Return m_ms
End Get
Set(ByVal value As Double)
m_ms = value
End Set
End Property
Public ReadOnly Property Performance As String
Get
Return String.Format("{0:f2}%", 100 * m_perf)
End Get
End Property
End Class
' start, last, expected
Private ReadOnly tests As TestsInfo() = {
New TestsInfo(1, 1, 1L),
New TestsInfo(1, 2, 3L),
New TestsInfo(1, 3, 3L),
New TestsInfo(1, 10, 37L),
New TestsInfo(1, 13, 48L),
New TestsInfo(1, 20, 134L),
New TestsInfo(3, 3, 0),
New TestsInfo(3, 4, 4L),
New TestsInfo(3, 5, 9L),
New TestsInfo(3, 6, 9L),
New TestsInfo(3, 9, 24L),
New TestsInfo(13, 13, 0),
New TestsInfo(13, 23, 108L),
New TestsInfo(100, 1000, 249976L),
New TestsInfo(1, 100, 2872L),
New TestsInfo(3, 103, 2970L),
New TestsInfo(123, 456, 32130L),
New TestsInfo(300, 4000, 2192728L),
New TestsInfo(332, 3332, 2188728L),
New TestsInfo(777, 7777, 12814264L),
New TestsInfo(999, 9999, 22425984L),
New TestsInfo(1, 999999, 183707816292L)
}
Private fnCalc As Func(Of Long, Long, Long)
Private Const NUM_BENCHMARK As Integer = 50
Private Sub Button1_Click() Handles Button1.Click
Dim actions As Func(Of Long, Long, Long)() = {
AddressOf Calc1,
AddressOf Calc2,
AddressOf Calc3
},
ubActions = actions.GetUpperBound(0),
benchmarkElapsed(ubActions) As Double,
avgElapsed As Double = 0,
lstResult As IBindingList =
New BindingList(Of BenchmarkResult)
Me.Text = "Benchmarking...Please wait"
' benchmark
For i As Integer = 0 To ubActions
fnCalc = actions(i)
benchmarkElapsed(i) = Benchmark(AddressOf DoCalc, NUM_BENCHMARK)
avgElapsed += benchmarkElapsed(i)
Next
avgElapsed /= (ubActions + 1)
' output the result
For i As Integer = 0 To ubActions
Dim benchmarkResult As New BenchmarkResult(i,
actions(i).Method.Name,
benchmarkElapsed(i))
benchmarkResult.CalcPerf(avgElapsed)
lstResult.Add(benchmarkResult)
Next
' configure datagridview
DataGridView1.DataSource = lstResult
DataGridView1.AutoResizeRows()
DataGridView1.AutoResizeColumns()
Me.Text = "Completed"
End Sub
Private Function Benchmark(ByVal fn As Action,
ByVal testTimes As Integer) As Double
Dim sw As New Stopwatch,
times As Integer = testTimes
sw.Start()
While times <> 0
fn()
times -= 1
End While
sw.Stop()
Return sw.ElapsedMilliseconds / testTimes
End Function
Private Sub DoCalc()
Dim ret As Long
For i As Integer = 0 To tests.GetUpperBound(0)
Dim test As TestsInfo = tests(i)
ret = fnCalc(test.start, test.last)
Debug.Assert(test.expected = ret,
String.Format("Wrong result, expected {0} but got {1}. " &
"Index is {2}, from {3} to {4}",
test.expected,
ret,
i,
test.start,
test.last)
)
Next
End Sub
Private Function Calc1(ByVal numStart As Long,
ByVal numLast As Long) As Long
Dim sum As Long = 0
For i As Long = numStart To numLast
Dim s As String = i.ToString()
If 0 <> i Mod 3 AndAlso
-1 = s.IndexOf("3"c) Then
sum += i
End If
Next
Return sum
End Function
Private Function Calc2(ByVal numStart As Long,
ByVal numLast As Long) As Long
Dim sum As Long = 0,
start As Long,
last As Long
For i As Long = 1 To 2
start = ((numStart - 1 + i) \ 3 + 1) * 3 - i
last = ((numLast + i) \ 3) * 3 - i
For j As Long = start To last Step 3
Dim s As String = j.ToString()
If -1 = s.IndexOf("3"c) Then
sum += j
End If
Next
Next
Return sum
End Function
Private Function Calc3(ByVal numStart As Long,
ByVal numLast As Long) As Long
Dim sum As Long = 0
For i As Long = 1 To 2
Dim start As Long = ((numStart - 1 + i) \ 3 + 1) * 3 - i,
last As Long = ((numLast + i) \ 3) * 3 - i
For j As Long = start To last Step 3
Dim k As Long = j
Do
If 3 = k Mod 10 Then
Exit Do
End If
k \= 10
Loop While 0 <> k
If 0 = k Then
sum += j
End If
Next
Next
Return sum
End Function
End Class 程式建構說明:Visual Studio 建 VB Windows Application 拉一個 Button (Button1) 和 DataGridView (DataGridView1) Form1 程式碼改成以上程式碼 程式代碼說明:tests 是作為驗證正確性用, fnCalc 是函數的位址,傳給 DoCalc 使用 Benchmark 會跑 DoCalc NUM_BENCHMARK 次然後傳回平均花費時間 編譯環境在 Debug 結果: Calc3 大概快了 2 倍 編譯環境在 Release 結果: (可以勾選 Project Properties -> Compile -> Advanced Compile Options -> Optimization 的兩個選項達到更快的運算速度) Calc3 大概快了 6 倍
[ 此文章被ebolaman在2013-09-21 14:10重新編輯 ]
|
|
|