广告广告
  加入我的最爱 设为首页 风格修改
首页 首尾
 手机版   订阅   地图  繁体 
您是第 4072 个阅读者
 
发表文章 发表投票 回覆文章
  可列印版   加为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.041943 second(s),query:16 Gzip disabled
本站由 瀛睿律师事务所 担任常年法律顾问 | 免责声明 | 本网站已依台湾网站内容分级规定处理 | 连络我们 | 访客留言