廣告廣告
  加入我的最愛 設為首頁 風格修改
首頁 首尾
 手機版   訂閱   地圖  簡體 
您是第 4129 個閱讀者
 
發表文章 發表投票 回覆文章
  可列印版   加為IE收藏   收藏主題   上一主題 | 下一主題   
cz910021 手機
個人文章 個人相簿 個人日記 個人地圖
小有名氣
級別: 小有名氣 該用戶目前不上站
推文 x27 鮮花 x43
分享: 轉寄此文章 Facebook Plurk Twitter 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片
推文 x0
[Basic][求助] vb算數
我的程式老師給我的題目
讓使用者以TextBox(文字長度限定8位)輸入起始值及結束值,計算此範圍內的整數和,但含有數字3及3的倍數的數字除外。
例如,若要計算1~20的整數和,但3及13含有數字3,且3、6、9、12、15、18均為3的倍數,因此計算時只加總1+2+4+5+7+8+10+11+14+16+17+19+20=134。

這是我打的

        Dim x, y, a As String, i, j, k As Integer : x = TextBox1.Text : y = TextBox2.Text
        Dim t As Boolean = False : a = 0
        If x > y Then
           ..

訪客只能看到部份內容,免費 加入會員 或由臉書 Google 可以看到全部內容



還差20威望
獻花 x0 回到頂端 [樓 主] From:IANA | Posted:2013-09-15 13:26 |
cz910021 手機
個人文章 個人相簿 個人日記 個人地圖
小有名氣
級別: 小有名氣 該用戶目前不上站
推文 x27 鮮花 x43
分享: 轉寄此文章 Facebook Plurk Twitter 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片

更新後

    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


還差20威望
獻花 x0 回到頂端 [1 樓] From:IANA | Posted:2013-09-15 17:19 |
ebolaman 手機 會員卡
個人文章 個人相簿 個人日記 個人地圖
特殊貢獻獎

級別: 副版主 該用戶目前不上站
版區: 程式設計
推文 x38 鮮花 x458
分享: 轉寄此文章 Facebook Plurk Twitter 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片

我用 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 倍


本帖包含附件
zip Form1 code.rar   (2022-06-09 14:21 / 3 KB)   下載次數:1


[ 此文章被ebolaman在2013-09-21 14:10重新編輯 ]


My BOINC stats :

獻花 x0 回到頂端 [2 樓] From:台灣寬頻通訊顧問股份有限公司 | Posted:2013-09-21 14:00 |

首頁  發表文章 發表投票 回覆文章
Powered by PHPWind v1.3.6
Copyright © 2003-04 PHPWind
Processed in 0.057162 second(s),query:16 Gzip disabled
本站由 瀛睿律師事務所 擔任常年法律顧問 | 免責聲明 | 本網站已依台灣網站內容分級規定處理 | 連絡我們 | 訪客留言