|
楼主 |
发表于 2007-3-19 00:26
|
显示全部楼层
<p><strong>VBA第1期接力赛情况总述(二)</strong></p><p>本次竞赛共收到bifengXia,plz001,LJW17,uranus1997,戏子,danielcm六位会员有效答案6份,正确性验证取N=2,6,100,200,300,速度评价取N=300。测试环境为Duron700/256M,WinXP+Excel2003。以下是参评代码(根据需要部分代码做了非实质性修改)及测试评价:<br/><strong>'--*-- bifengXia --*--</strong><br/>Sub BiFengXia()<br/> Dim i As Integer, j As Integer, k As Integer, t As Single, iNowRow As Integer<br/> t = Timer<br/> Range("A:A").Clear<br/> k = Int(Range("B1").Value)<br/> If k < 2 Then<br/> MsgBox "在B1单元格输入一个大于等于 2 的整数!", , "BiFengXia"<br/> Range("B1").Select<br/> Exit Sub<br/> End If<br/> Application.ScreenUpdating = False<br/> On Error GoTo 100<br/> iNowRow = 1 '当前行<br/> For i = 1 To k 'i为分母<br/> For j = 1 To i - 1 'j为分子,它的值在1到i-1之间,用自定义函数判断j与i是否能够组成真分数<br/> If ProperFraction(j, i) Then<br/> Cells(iNowRow, 1).Value = "'" & j & "/" & i '如果是真分数,将分数写入A列<br/> Cells(iNowRow, 2).Value = j / i '如果是真分数,将小数写入B列<br/> iNowRow = iNowRow + 1 '下移一行<br/> End If<br/> Next j<br/> Next i<br/> '根据B列的临时值(小数)扩展排序,按升充排列<br/> Range("A1:B" & iNowRow).Sort Key1:=Range("B1"), Order1:=xlAscending, Header:= _<br/> xlGuess, OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _<br/> SortMethod:=xlPinYin, DataOption1:=xlSortNormal<br/> Range("B:B").Clear '清楚B列的临时值<br/> Range("B1").Select<br/> Range("B1").Value = k<br/> Application.ScreenUpdating = True<br/> MsgBox "共用时:" & (Timer - t) * 1000 & "毫秒!", , "BiFengXia"<br/> Exit Sub<br/>100:<br/> MsgBox "结果超出运算的最大行,产生了溢出!请最好将B1单元格的数值减小到320以内。", , "BiFengXia"<br/> Range("A:B").Clear<br/> Range("B1").Value = k<br/> Range("B1").Select<br/>End Sub</p><p>'自定义函数,测试是否为真分数(分子为number1,分母为number2)<br/>rivate Function ProperFraction(number1 As Integer, number2 As Integer) As Boolean<br/> ProperFraction = True<br/> If number2 Mod number1 = 0 And number1 > 1 Then '如果分子能够被分母整除,则不是真分数,返回结果<br/> ProperFraction = False<br/> Exit Function<br/> End If<br/> Dim k As Integer<br/> 'For k = 2 To (number1 + 2) / 2<br/> For k = 2 To number1<br/> If number1 Mod k = 0 And number2 Mod k = 0 Then '如果分子与分母有公约数,则不是真分数,返回结果<br/> ProperFraction = False<br/> Exit Function<br/> End If<br/> Next k<br/>End Function<br/>------<br/><u>结果:正确 用时:26.29秒<br/>代码结构清晰,书写规范。输出结果为文本格式,如修改为按分数形式输出,速度应当更快。</u></p><p><strong>'--*-- plz001 --*--</strong><br/>rivate Sub CommandButton1_Click()<br/> Application.ScreenUpdating = False<br/> M = Timer<br/> Columns("A:A").ClearContents<br/> Columns("A:A").NumberFormatLocal = "# ???/???"<br/> v = Cells(1, 2)<br/> If v = 2 Then [a1] = 0.5: Exit Sub<br/> r = 0 '在数组中生成分数列,速度快<br/> ReDim arrl(1 To (v * (v - 1) / 2), 0)<br/> For i = 2 To v<br/> For t = 1 To i - 1<br/> r = r + 1<br/> arrl(r, 0) = t / i<br/> Next t<br/> Next i<br/> Range("A1:A" & r) = arrl<br/> Set arr = Range("a1:a" & r) '对对象变量的操作比直接访问对象速度快<br/> arr.Sort Key1:=arr(1, 1), Order1:=xlAscending, Header:=xlNo<br/> rng1 = arr '?????<br/> ReDim ary(1 To r, 0) '排序后再筛选,这样的算法快<br/> ary(1, 0) = rng1(1, 1)<br/> For i = 2 To r<br/> If rng1(i, 1) <> rng1(i - 1, 1) Then<br/> ary(k + 2, 0) = rng1(i, 1)<br/> k = k + 1<br/> End If<br/> Next i<br/> Range("A1:A" & r) = ary<br/> Application.ScreenUpdating = True<br/> MsgBox Timer - M<br/>End Sub<br/>------<br/><u>结果:正确 用时:1.48秒<br/>精益求精,每一次都给我惊喜,能够在这么短时间内掌握数组的使用,除了天资聪颖,更可赞学习探索之精神可嘉。<br/>“对对象变量的操作比直接访问对象速度快”我测试的结果没有得到证实。建议以后在书写代码时使用变量声明(Option Explicit),细节上如边缘数据,运行环境预清理等等要注意考虑,良好的代码习惯的会使进步更快。</u></p><p><strong>'--*-- LJW17 --*--</strong><br/>Sub zhengFS()<br/> ' 从B1单元格读取一个任意整数,按从小到大顺序求出分子、分母均不大于该整数的真分数。<br/> Dim n As Integer '读取整数存放的变量<br/> Dim feimu() As Long '求出结果分母存放的数组<br/> Dim feizi() As Long '求出结果分子存放的数组<br/> Dim lp1, lp2 '循环变量<br/> Dim gesu As Long '求出结果的个数<br/> gesu = 0 '个数赋0<br/> n = Cells(1, 2).Value '读出整数<br/> ReDim feimu(CLng(n) * CLng(n - 1) / 2) '根据n重新定义分母、分子数组的大小<br/> ReDim feizi(CLng(n) * CLng(n - 1) / 2) '因计算结果可能为Long型,为防止溢出错误,需要使用CLng转换函数<br/> For lp1 = 2 To n '分母循环<br/> For lp2 = 1 To lp1 - 1 '分子循环<br/> If lp2 = 1 Then '判断分子是否为1,是则肯定是真分数<br/> gesu = gesu + 1 '个数加1,并保存好分子、分母<br/> feimu(gesu) = lp1<br/> feizi(gesu) = lp2<br/> Else<br/> If zhengfeisu(lp2, lp1) Then '判断是否为真分数,是则保存,否则不保存<br/> gesu = gesu + 1<br/> feimu(gesu) = lp1<br/> feizi(gesu) = lp2<br/> End If<br/> End If<br/> Next lp2<br/> Next lp1<br/> For lp1 = 1 To gesu '通过冒泡排序,将求出的真分数存放的数组按小到大排序<br/> feimu(0) = feimu(lp1)<br/> feizi(0) = feizi(lp1)<br/> For lp2 = lp1 + 1 To gesu '求出一组数中的最小值,并将最小值移到前面<br/> If feizi(0) / feimu(0) > feizi(lp2) / feimu(lp2) Then<br/> feizi(lp1) = feizi(lp2)<br/> feimu(lp1) = feimu(lp2)<br/> feizi(lp2) = feizi(0)<br/> feimu(lp2) = feimu(0)<br/> feizi(0) = feizi(lp1)<br/> feimu(0) = feimu(lp1)<br/> End If<br/> Next lp2<br/> Next lp1<br/> Range("a:a").Clear '清空A列<br/> For lp1 = 1 To gesu '将求出并排好序的真分数写入A列中<br/> Cells(lp1, 1).Value = "'" + CStr(feizi(lp1)) + "/" + CStr(feimu(lp1))<br/> Next lp1<br/>End Sub</p><p>Function zhengfeisu(i, j) As Boolean<br/>''******************************************************************************<br/>''** 判断分子为i,分母为j的分数是否真分数,是则还加True,否则还False **<br/>''******************************************************************************<br/> Dim lp3<br/> zhengfeisu = True '假设该数是真分数<br/> If j / i <> j \ i Then '判断分母、分子是否能够整除<br/> For lp3 = 2 To i \ 2 '不能整除则循环求出分子、分母是否存在公约数<br/> If i Mod lp3 = 0 And j Mod lp3 = 0 Then<br/> zhengfeisu = False '存在公约数则不是真分数<br/> Exit For<br/> End If<br/> Next lp3<br/> Else<br/> zhengfeisu = False '如果分母、分子能够整除则不是真分数<br/> End If<br/>End Function<br/>------<br/><u>结果:正确 用时:596秒<br/>结构清晰规范,详尽的注释很难得,冒泡排序对大数据的处理效率很低。</u></p><p></p> |
|