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重新编辑 ]
|
|
|