下面是我的代码:
Dim temrecord2(360, 1) As Long
Dim i, j, k, l, f As Integer
Dim count As Integer
Dim cx, cy, csx, csy As Long
Dim jl As Single For l = 0 To 360
For i = 0 To 360
If i - l < 0 Then
temrecord(i, 0) = record(i - l + 360, 0)
Else
temrecord(i, 0) = record(i - l, 0)
End If
temrecord(i, 1) = 1
Next
For f = 0 To 360
For j = 0 To 360
csx = Int((basicrecord(f, 0) * Cos(f * pi180) - temrecord(j, 0) * Cos(j * pi180)))
csy = Int((basicrecord(f, 0) * Sin(f * pi180) - temrecord(j, 0) * Sin(j * pi180)))
count = 0 For k = 0 To 360
cangle = (k + 90) * pi180
cx = (temrecord(k, 0)) * Sin(cangle) + csx
cy = (temrecord(k, 0)) * Cos(cangle) + csy jl = Sqr((cx - temrecord2(1, 0)) ^ 2 + (cy - temrecord2(1, 1)) ^ 2)
If jl > Val(Text7.Text) Then
count = count + 1
End If
If count > 180 Then Exit For
Next
DoEvents
Next
Next
Next就这些运算,要完成就需要差不多20个小时,根本无法接受~
请问还能提高运算效率吗?
要如何改呢?
Dim temrecord2(360, 1) As Long
Dim i, j, k, l, f As Integer
Dim count As Integer
Dim cx, cy, csx, csy As Long
Dim jl As Single For l = 0 To 360
For i = 0 To 360
If i - l < 0 Then
temrecord(i, 0) = record(i - l + 360, 0)
Else
temrecord(i, 0) = record(i - l, 0)
End If
temrecord(i, 1) = 1
Next
For f = 0 To 360
For j = 0 To 360
csx = Int((basicrecord(f, 0) * Cos(f * pi180) - temrecord(j, 0) * Cos(j * pi180)))
csy = Int((basicrecord(f, 0) * Sin(f * pi180) - temrecord(j, 0) * Sin(j * pi180)))
count = 0 For k = 0 To 360
cangle = (k + 90) * pi180
cx = (temrecord(k, 0)) * Sin(cangle) + csx
cy = (temrecord(k, 0)) * Cos(cangle) + csy jl = Sqr((cx - temrecord2(1, 0)) ^ 2 + (cy - temrecord2(1, 1)) ^ 2)
If jl > Val(Text7.Text) Then
count = count + 1
End If
If count > 180 Then Exit For
Next
DoEvents
Next
Next
Next就这些运算,要完成就需要差不多20个小时,根本无法接受~
请问还能提高运算效率吗?
要如何改呢?
解决方案 »
- VB使用xp_cmdshell的问题
- 【新手】关于两个listbox
- 如何让VB执行一个非exe扩展名的执行文件?(有点绕口)
- 如何判断Text控件中的内容是否为字母?
- 请教各位高手:如何用vb获得硬盘序列号?
- 一个简单的问题,怎么用dir函数返回"c:\temp"目录下的子目录?
- 有没有函数可以从Html文本中分析出要在浏览器中显示的字符呀?
- 谁有Active Threed Plus V3.03.3 的Cd_key Or Sn
- 我在窗体上动态加载了控件,如何判断该控件是不是已存在?
- 一个程序在运行时把自身拷到c:盘,并删除自已。怎么做到?(注:编写时并不知道程序会在哪个路径下)
- 分两列显示的下拉控件
- 程序员未来走势及抉择
1--Dim temrecord2(360, 1) As Long
二维数组的第二维就只有0,1个值,不知能否用两个一维数组来代替?2--Dim i, j, k, l, f As Integer
改为Dim i As Integer , j As Integer , k As Integer , l As Integer , f As Integer3--Dim cx, cy, csx, csy As Long 类似2
4--给每个Next后面添上对应的 i、j、k等计数因子。
csy = Int((basicrecord(f, 0) * Sin(f * pi180) - temrecord(j, 0) * Sin(j *
这两句里面的
(basicrecord(f, 0) * Cos(f * pi180)和
(basicrecord(f, 0) * Sin(f * pi180)
属于重复计算,完全可以把这部分放到j循环外面temrecord(k, 0))也一样
这两个图形比较简单,可以看多是两个圆,一个圆有360个点组成,通过改变第二个圆的角度,和位置,不断与第一个圆比较,从而判断出,第二个圆相对与第一个圆旋转了的角度有多少,位移有多少~~现在我把吻合度小于50%的就跳出对比的循环,提高了一倍效率。当第二个圆的圆心移出第一圆时不进行判断,效率又提高了近一倍。
不过现在还要5-6小时,才能完成啊~~~还有没有好办法啊???
For l = 0 To 360
For i = 0 To 360
If i - l < 0 Then
temrecord(i, 0) = record(i - l + 360, 0)
Else
temrecord(i, 0) = record(i - l, 0)
End If
temrecord(i, 1) = 1
Next
For f = 0 To 360
bcy = basicrecord(f, 0) * Sin(f * pi180)
bcx = basicrecord(f, 0) * Cos(f * pi180)
For j = 0 To 360
contimerc = contimerc + 1
csx = Int((bcx - temrecord(j, 0) * Cos(j * pi180)))
csy = Int((bcy - temrecord(j, 0) * Sin(j * pi180)))
count = 0 If csx <> 0 Then '获取圆心移动的角度
If csy >= 0 And csx >= 0 Then
tangle = Int(Atn(csy / csx) / 3.1415926 * 180)
Else
If csx < 0 Then
tangle = Int((Atn(csy / csx) + 3.1415926) / 3.1415926 * 180)
Else
If csy < 0 And csx >= 0 Then
tangle = Int((Atn(csy / csx) + 2 * 3.1415926) / 3.1415926 * 180)
End If
End If
End If
Else
tangle = 0
End If If basicrecord(tangle, 0) >= Sqr(csx ^ 2 + csy ^ 2) Then '判断中心是否出了basicrecord
Picture1.Cls
showcom
showtem
For k = 0 To 360
cangle = (k + 90) * pi180
cy = (temrecord(k, 0)) * Sin(k * pi180) + csx
cx = (temrecord(k, 0)) * Cos(k * pi180) + csy jl = Sqr((cx - temrecord2(k, 1)) ^ 2 + (cy - temrecord2(k, 0)) ^ 2)
If jl > Val(Text7.Text) Then'text7.text为容差值
count = count + 1
End If
If count > 180 Then Exit For
Next
DoEvents End If
Next
Next
Next
把 0°~ 360°的正弦、余弦函数值预先处理,分别对应保存在一个 Double 类型的、下标为 0~360 的一维数组中,使用时直接以度数为下标,在数组中取值。
这个方法应该能大大提高速度。 ②你的变量声明方式不正确。产生了大量的 Variant 类型的变量,这很影响速度。 ③建议所有的变量,整数类型的都用 Long;Single 类型的都用 Double 。
特别是 Single 类型,可能很多人都不知道:在VB中,即使只有 Single 类型的数据参与运算,运算时也要先全部转换成 Double ,运算后再将结果转换成 Single 来赋值(当然赋值给 Double 类型的变量就不会再转了)。 ④9F 的第一项。
也能大大提高速度。
If jl > Val(Text7.Text) Then
..........Text7.Text 在整个过程中没有发生过变化,在进入第一层循环前,就用一个合适类型的变量保存它的值。在 If 语句中使用那个变量。本来转换一次就行的,何苦要它转换 360^4 = 16796160000次(最坏的情况,约168亿次啊)? 这浪费多少时间!!!
有声明的?
是有声明,但不正确。
你的“Dim i, j, k, l, f As Integer ”
只有 f 是 Integer,其余四个都是 Variant 类型。
'================== 旋转图形用 ========================================
Public Type POINTS2D
X As Long
Y As Long
End Type
Public Const NotPi = 3.14159265238 / 180 '每度的弧度数
Public Const Pi = 3.14159265238
Public Declare Function PlgBlt Lib "gdi32" (ByVal hdcDest As Long, lpPoint As POINTS2D, _
ByVal hdcSrc As Long, ByVal nXSrc As Long, _
ByVal nYSrc As Long, ByVal nWidth As Long, _
ByVal nHeight As Long, ByVal hbmMask As Long, _
ByVal xMask As Long, ByVal yMask As Long) As LongSub D中心转(ByRef picDestHdc As Long, xPos As Long, yPos As Long, Fd As Single, _
ByVal Angle As Long, ByRef picSrcHdc As Long, _
srcXoffset As Long, srcYoffset As Long, _
ByVal srcWidth As Long, ByVal srcHeight As Long)
' picDestHdc: 目标, xPos、yPos 中心坐标
' Fd 放大倍数 Angle 旋转角度
' srcYoffset: 源图,srcXoffset、srcYoffset、srcWidth、srcHeight 矩形范围
Dim points(3) As POINTS2D
Dim DefPoints(3) As POINTS2D
Dim ThetS As Single, ThetC As Single
Dim Ret As Long
points(0).X = -srcWidth * 0.5 * Fd
points(0).Y = -srcHeight * 0.5 * Fd
points(1).X = points(0).X + srcWidth * Fd
points(1).Y = points(0).Y
points(2).X = points(0).X
points(2).Y = points(0).Y + srcHeight * Fd
ThetS = Sin(Angle * NotPi)
ThetC = Cos(Angle * NotPi)
DefPoints(0).X = (points(0).X * ThetC - points(0).Y * ThetS) + xPos
DefPoints(0).Y = (points(0).X * ThetS + points(0).Y * ThetC) + yPos
DefPoints(1).X = (points(1).X * ThetC - points(1).Y * ThetS) + xPos
DefPoints(1).Y = (points(1).X * ThetS + points(1).Y * ThetC) + yPos
DefPoints(2).X = (points(2).X * ThetC - points(2).Y * ThetS) + xPos
DefPoints(2).Y = (points(2).X * ThetS + points(2).Y * ThetC) + yPos
PlgBlt picDestHdc, DefPoints(0), picSrcHdc, srcXoffset, srcYoffset, _
srcWidth, srcHeight, 0, 0, 0
End Sub
溜墙边偷偷插嘴问chen,你的圈1圈2圈3圈4,是怎么敲出来的?
你既然用的幂运算符,它就会按幂运算的方式来计算这个表达式。
幂如何运算?CPU能直接进行幂运算吗?
不能!秘密就是自然对数的底 e !!!你可以试一下简单的测试:
'(一个窗体,上面两个按钮、一个标签)
Option ExplicitPrivate Sub Command1_Click()
Dim i&, Q&, n&, t#
t = Timer()
n = 4506
For i = 1 To 15000000
Q = n ^ 2
Next
Label1.Caption = Timer() - t
End SubPrivate Sub Command2_Click()
Dim i&, Q&, n&, t#
t = Timer()
n = 4506
For i = 1 To 15000000
Q = n * n
Next
Label1.Caption = Timer() - t
End Sub指数运算耗时是乘法运算的100倍左右。我常用的智能陈桥。
要进行特殊的输入时,切换到王码五笔或全拼就可以了,它有软键盘,在上面点鼠标右键......
您加我,或者您留个mail或Q吧~
㈠ 正确的变量声明,能使integer型就不要用long型,能使long型就不double
㈡ 尽量采用低级运算,如可以提前拆分的能加减不乘除,虽然这样会在写公式前算一下,不过会提高速度
㈢ 正确的或优化的算法
Dim cosvalue(360) As Double
Dim record(360, 1) As Long, basicrecord(360, 1) As Long, temrecord(360, 1) As Long
Dim X As Long, delayt As Byte, scanspeed As Double, rad, maxv As Long, stops As Boolean, pw As Long, ph As Long, PWW As Long, PHH As Long, pi As Single, pi180 As Single
Public Sub showtem()
Dim i As Integer
Dim sxx, syy, sxx1, syy1 As LongFor i = 0 To 360
If temrecord(i, 1) = 1 Then
j = pi180 * (i + 90)
sxx = (temrecord(i, 0) / maxv / 10) * (rad) * Sin(j) + pw
syy = (temrecord(i, 0) / maxv / 10) * (rad) * Cos(j) + ph
Picture1.PSet (sxx, syy), vbBlue
If sxx1 <> 0 And syy1 <> 0 Then Picture1.Line (sxx, syy)-(sxx1, syy1), vbBlue
sxx1 = sxx
syy1 = syy
End If
Next
End SubPublic Sub showcom()
Dim i As Integer
Dim sxx, syy, sxx1, syy1 As LongFor i = 0 To 360
If basicrecord(i, 1) = 1 Then
j = pi180 * (i + 90)
sxx = (basicrecord(i, 0) / maxv / 10) * (rad) * Sin(j) + pw
syy = (basicrecord(i, 0) / maxv / 10) * (rad) * Cos(j) + ph
Picture1.PSet (sxx, syy), vbWhite
If sxx1 <> 0 And syy1 <> 0 Then Picture1.Line (sxx, syy)-(sxx1, syy1), vbWhite
sxx1 = sxx
syy1 = syy
End If
Next
End SubPublic Sub showrecord()
Dim i As Integer
Dim sxx, syy, sxx1, syy1 As LongPicture1.Cls
For i = 0 To 360
If record(i, 1) = 1 Then
j = pi180 * (i + 90)
sxx = (record(i, 0) / maxv / 10) * (rad) * Sin(j) + pw
syy = (record(i, 0) / maxv / 10) * (rad) * Cos(j) + ph
Picture1.PSet (sxx, syy), vbRed
If sxx1 <> 0 And syy1 <> 0 Then Picture1.Line (sxx, syy)-(sxx1, syy1), vbRed
sxx1 = sxx
syy1 = syy
End If
Next
End Sub
Private Sub Command1_Click()
Dim temrecord2(360, 1) As Long
Dim i As Long, j As Long, k As Long, l As Long, f As Long
Dim count As Long
Dim cx As Long, cy As Long, csx As Long, csy As Long
Dim bcy As Double, bcx As Double
Dim jl As Double
Dim tangle As Long
Dim tolerance As Long
Dim p180 As Double
Dim maxcount As Long
contimerc = 0 tolerance = Val(Text1.Text)For l = 0 To 360
temrecord2(l, 0) = (basicrecord(l, 0)) * sinvalue(l)
temrecord2(l, 1) = (basicrecord(l, 0)) * cosvalue(l)
Next For l = 0 To 360
For i = 0 To 360
If i - l < 0 Then
temrecord(i, 0) = record(i - l + 360, 0)
Else
temrecord(i, 0) = record(i - l, 0)
End If
temrecord(i, 1) = 1
Next
For f = 0 To 360
bcy = basicrecord(f, 0) * sinvalue(f)
bcx = basicrecord(f, 0) * cosvalue(f)
For j = 0 To 360
contimerc = contimerc + 1
csx = Int((bcx - temrecord(j, 0) * cosvalue(j)))
csy = Int((bcy - temrecord(j, 0) * sinvalue(j)))
count = 0 If csx <> 0 Then '获取圆心移动的角度
If csy >= 0 And csx >= 0 Then
tangle = Int(Atn(csy / csx) / 3.1415926 * 180)
Else
If csx < 0 Then
tangle = Int((Atn(csy / csx) + 3.1415926) / 3.1415926 * 180)
Else
If csy < 0 And csx >= 0 Then
tangle = Int((Atn(csy / csx) + 2 * 3.1415926) / 3.1415926 * 180)
End If
End If
End If
Else
tangle = 0
End If If basicrecord(tangle, 0) >= Sqr(csx * csx + csy * csy) Then '判断中心是否出了basicrecord
Picture1.Cls
showcom
showtem For k = 0 To 360
cangle = (k + 90) * pi180
cy = (temrecord(k, 0)) * sinvalue(k) + csx
cx = (temrecord(k, 0)) * cosvalue(k) + csy
Picture1.PSet (sxx, syy), vbBlue
sxx = (temrecord(k, 0) / maxv / 10) * (rad) * Sin(cangle) + pw + csx / maxv / 10 * rad
syy = (temrecord(k, 0) / maxv / 10) * (rad) * Cos(cangle) + ph + csy / maxv / 10 * rad
If sxx1 <> 0 And syy1 <> 0 Then Picture1.Line (sxx, syy)-(sxx1, syy1), vbBlue
sxx1 = sxx
syy1 = syy
jl = Sqr((cx - temrecord2(k, 1)) ^ 2 + (cy - temrecord2(k, 0)) ^ 2)
If jl > tolerance Then
count = count + 1
End If
If count > 180 Then Exit For
Next
If maxcount > count Then
maxcount = count
End If
DoEvents
Debug.Print Str((360 - count) / 360 * 100) + "%:::::::::" + Str(j) + "::::::::::" + Str(f) + "::::::::::::" + Str(l)
End If
Next
Next
Next
Label1.Caption = 360 - maxcount
End SubPrivate Sub Form_Load()rad = Picture1.Width / 2 - 58
maxv = 500
pw = Picture1.Width / 2
ph = Picture1.Height / 2
pi180 = 3.1415926 / 180For i = 0 To 180
basicrecord(i, 0) = i * 20
basicrecord(i, 1) = 1
record(i, 0) = (180 - i) * 20
record(i, 1) = 1
Next
For i = 181 To 360
basicrecord(i, 0) = (180 - (i - 180)) * 20
basicrecord(i, 1) = 1
record(i, 0) = (i - 180) * 20
record(i, 1) = 1
Next
For l = 0 To 360
sinvalue(l) = Sin(pi180 * l)
cosvalue(l) = Cos(pi180 * l)
Next
End Sub
只是为了表示运算过程才画图的下面这些代码可以不要
Picture1.Cls
showcom
showtem Picture1.PSet (sxx, syy), vbBlue
sxx = (temrecord(k, 0) / maxv / 10) * (rad) * Sin(cangle) + pw + csx / maxv / 10 * rad
syy = (temrecord(k, 0) / maxv / 10) * (rad) * Cos(cangle) + ph + csy / maxv / 10 * rad
If sxx1 <> 0 And syy1 <> 0 Then Picture1.Line (sxx, syy)-(sxx1, syy1), vbBlue
sxx1 = sxx
syy1 = syy
在32位操作系统上,4字节的long型变量是最快的
所以,应该是“能使用long就不适用integer”
要1个小时?
多大的图片呀?有这么慢吗~~~~ -_-!可不可以弄两三张图片,打个压缩包发给我看一看呀?
E_Mail: [email protected]
“能使用long就不用integer”
这个是真的吗?我的计算程序可以全部更换了。从这个帖子学到了很多。
参看MSDN“代码优化”部分:使用 Long 整型变量和整数运算
算术运算中要避免使用 Currency、Single 和 Double 变量;并尽量使用 Long 整型变量,尤其在循环体中。因为 Long 整数是 32 位 CPU 的本机数据类型,所以其操作非常快;如果无法使用 Long 变量,就要尽量使用 Integer 或 Byte 数据类型。很多时候,即使在要求使用浮点数的情况下,也可以使用 Long 整数。例如,在窗体和图形控件的 ScaleMode 属性设置为缇或象素时,就可以在控件和图形方法中使用 Long 整型变量表示大小和位置。进行除法运算时,如果不需要小数部分,就可以使用整数除法运算符 (/)。由于浮点运算需要转移到协处理器上进行,而整数运算并不需要,所以整数运算总是比浮点运算快。如果确实需要做小数运算,则 Double 数据类型比 Currency 数据类型快。下表把各种数值数据类型按运算速度顺序列出。数值数据类型 速度
Long 最快
Integer .
Byte .
Single .
Double .
Currency 最慢
temrecord(i, 0) = record(i - l + 360, 0)
Else
temrecord(i, 0) = record(i… 想一下概率吧!那个该放前面减少判断。
现在还需要40分钟左右啊
楼主的算法思路是否这样的:将一幅图旋转某一角度,与另一幅图比对?其实应该分两阶段来做:
1 首先选取 A 图几个点,做旋转映射,与 B 图比对。算一个,比一个,有一个不同,就跳出到下一个角度。只有全部相同,才进入下一步。
2 对你做相同判断所需的所有点,做旋转映射和比对。只要有一个不同,就跳出到下一个角度。也许要更好的算法,不需要这样一一比对。另外,如果 B 图是 A 图非整数角度的旋转映射,又怎么办?