标题的表达可能不准确,实际的意思:
大家知道,VB中的integer是有符号数,即最高位是表示符号的,最高位为1为负数。现在我在解析DDS图像格式,就遇到了这样的问题,在某一个步骤中,我需要比较两个占用2个字节的整数的大小,原始的C代码可以用C中的无符号整数的数据类型读取这两个数,然后直接用>运算符比较,而VB中只能用先把这两个字节的数读入两个integer变量中,但是这个时候VB中的>运算符返回的结果就不一定的正确的结果了。一个简单的做法就是用copymemory把integer变量拷贝到long 变量后在比较,但是这个在大循环中就会成为影像速度的瓶颈。我还没有仔细考虑这个问题的优化方法,先发个帖子让大家帮忙先想想把。
大家知道,VB中的integer是有符号数,即最高位是表示符号的,最高位为1为负数。现在我在解析DDS图像格式,就遇到了这样的问题,在某一个步骤中,我需要比较两个占用2个字节的整数的大小,原始的C代码可以用C中的无符号整数的数据类型读取这两个数,然后直接用>运算符比较,而VB中只能用先把这两个字节的数读入两个integer变量中,但是这个时候VB中的>运算符返回的结果就不一定的正确的结果了。一个简单的做法就是用copymemory把integer变量拷贝到long 变量后在比较,但是这个在大循环中就会成为影像速度的瓶颈。我还没有仔细考虑这个问题的优化方法,先发个帖子让大家帮忙先想想把。
Dim a(3) As Integer
Dim i As Long
Dim j As Long
a(0) = 0
a(1) = &H7FFF
a(2) = &H8000
a(3) = &HFFFF
For i = 0 To 3
For j = 0 To 3
Debug.Print a(i), "&H" & Hex(a(i)), a(j), "&H" & Hex(a(j)), UInt16Comp(a(i), a(j))
Next
Next
End SubFunction UInt16Comp(ByVal v1 As Integer, ByVal v2 As Integer) As Integer
Dim l1 As Long
Dim l2 As Long
l1 = CLng(v1) And &HFFFF&
l2 = CLng(v2) And &HFFFF&
UInt16Comp = Sgn(l1 - l2)
End Function
可能我没理解你意思。
l2 = CLng(v2) And &HFFFF&
实质还是借用long类型来比较。
要比较第I个数的大小,先比Bits(1,I),如果一样大,再比Bits(0,I)
不知道这样能否解决楼主的问题.
Else
EndIf 注: 这样可能还是影响速度2.判断大小时, 特别处理: Dim bFirstIntMax As Boolean
bFirstIntMax = False
If Int1 < 0 And Int2 < 0 Then
'直接比较
If Int1 > Int2 Then bFirstIntMax = True
Else
If Int1 < 0 Then
bFirstIntMax = True
Else
If Int2 < 0 Then
Else
If Int1 > Int2 Then bFirstIntMax = True
EndIf
EndIf 注: 这样可能还是影响速度你可以测一测, 这是在不转换数据类型的情况下想出的办法, 如果要转换数据类型, 我想一样要影响效率!
大伙一起再想一想吧...
直接从一个VB的integer类型变量来的,这当然是不可能,否则就不存在楼主的问题了.
那么这个无符号int数据就很可能是从内存或文件上来的.
再想一下,如果只有一个或几个数,那么即使用copymemory或类型转换也不麻烦,并且也慢不到哪里去.
那么剩下的可能就只能是内存或文件中的一大段双字节数据了.因为套上大循环之后copymemory的速度肯定是很低的.
直接将这段无符号int数据复制到VB的long型数组也是有问题的,因为元素长度不同存在对齐的问题.
所以我的想法是复制到一个二维byte数组内,不过后来想想直接复制到一维的byte数组性能更好,反正只要记得每2个元素代表原来的一个数就行了.
但是如果这个int除了比较大小,还要进行拆分的话,那转化为byte有可能并不会带来任何好处,(比如555,或565的颜色分量分离),因为还是要合并到一个long型变量里再用除法拆开,反而更麻烦了.
归根结底,因为缺乏足够的基本数据类型和真正的位操作,VB在处理这样数据时往往需要在性能上做一些妥协的.
最后祝楼主早日出关啊,给VB版增添生气.
Private Type Dxt1Block
Color(1) As Integer
Row(3) As Byte
End Type有这样一个结构体然后我在读取文件数据时候在一个循环中用到类似于下面的代码
ReadFile FileNumber, Block,len(Block), BytesRead, ByVal 0&
这个结构体的Color(0)和Color(1)就是用来比较大小的那两个数。
如果你把结构体的声明改为long,那读取的数据就不是正确的了。
BMP\JPG\PNG\GIF\TIF\ICO\WMF\EMF\PSD\PNM\TGA\PCX\WBM\XWD\DCM\FIT\IFF\SGI\XBM\RAS\DDS\PBT 这22种图像格式。
Red = ((Color And &H7800) \ 2048 - (Color And &H8000) \ 2048) * 255 \ 248
Green = ((Color And &H7E0) \ 32) * 255 \ 252
Blue = (Color And &H1F) * 255 \ 248这里的 255 \ 248我在一个C的代码上他是这样处理的Red = (Color And &H7800) \ 2048 - (Color And &H8000) \ 2048
Green = (Color And &H7E0) \ 32
Blue = Color And &H1F
Red = (Red * 8) Or (Red \ 4)
Green = (Green * 4) Or (Green \ 16)
Blue = (Blue * 8) Or (Blue \ 4)
在不转换数据类型的情况下实现比价 -1 最大 0最小
经过测试 比转换为 Long值再比较要快 Dim bFirstIntMax As Boolean, int1 As Integer, int2 As Integer
int1 = 800
int2 = -800
If (int1 < 0) Eqv (int2 < 0) Then ' 都是正数(含0) 或都是负数直接比
bFirstIntMax = int1 > int2
Else
bFirstIntMax = int2 < int1' 反之 反过来比
End If
Dim bFirstIntMax As Boolean, int1 As Integer, int2 As Integer
int1 = 800
int2 = -800
If (int1 < 0) Eqv (int2 < 0) Then ' 都是正数(含0) 或都是负数直接比
bFirstIntMax = int1 > int2
Else
bFirstIntMax = int2 > int1' 反之 反过来比
End If
if (int1 > int2) And (int1 < 0) Eqv (int2 < 0) then代替
int1 --> lon1 '类型转换
int2 --> lon2
if lon1 > lon2 then
'窗体上加1个多行 TextBox,2个 CommandButton'
Option Explicit
Private Const LOOP_COUNT As Long = 1000000Private Sub AddLog(ByVal Text As String)
With Text1
.SelStart = &HFFFF&
.SelText = Text & vbCrLf
End With
End SubPrivate Sub Command1_Click()
Dim fStart As Single
Dim fFinish As Single
Dim a(3) As Integer
Dim c As Long
Dim i As Long
Dim j As Long
Dim b As Boolean
a(0) = 0
a(1) = &H7FFF
a(2) = &H8000
a(3) = &HFFFF
fStart = Timer()
For c = 1 To LOOP_COUNT
For i = 0 To 3
For j = 0 To 3
b = (CLng(a(i)) And &HFFFF&) > (CLng(a(j)) And &HFFFF&)
Next
Next
Next
fFinish = Timer()
AddLog "Test1 : " & Format$(fFinish - fStart, "0.000")
End SubPrivate Sub Command2_Click()
Dim fStart As Single
Dim fFinish As Single
Dim a(3) As Integer
Dim c As Long
Dim i As Long
Dim j As Long
Dim b As Boolean
a(0) = 0
a(1) = &H7FFF
a(2) = &H8000
a(3) = &HFFFF
fStart = Timer()
For c = 1 To LOOP_COUNT
For i = 0 To 3
For j = 0 To 3
b = (a(i) > a(j)) And (a(i) < 0) Eqv (a(j) < 0)
Next
Next
Next
fFinish = Timer()
AddLog "Test2 : " & Format$(fFinish - fStart, "0.000")
End Sub
Dim bFirstIntMax As Boolean, int1 As Integer, int2 As Integer
int1 = -1
int2 = 800
t = Timer
For i = 1 To 10000000 '
' If (int1 < 0) Eqv (int2 < 0) Then
' bFirstIntMax = int1 > int2
' Else
' bFirstIntMax = int1 < int2
' End If
bFirstIntMax = (int1 > int2) And (int1 < 0) Eqv (int2 < 0)
NextDebug.Print (Timer - t) * 1000 ' 500-600
End Sub
Sub test2()
Dim bFirstIntMax As Boolean
Dim int1 As Integer, int2 As Integer, l1 As Long, l2 As Long
int1 = -1
int2 = 800
t = Timer
For i = 1 To 10000000 '
l1 = CLng(int1) And &HFFFF&
l2 = CLng(int2) And &HFFFF&
' bFirstIntMax = l1 > l2
NextDebug.Print (Timer - t) * 1000 ' 仅转换700-800 ,激活比较 1000+
End Sub
1)在模块头部定义
Private i As Variant '等同于你现在不声明变量的方式'
test1 359.375
test2 484.375
2)在模块头部定义
Private i As Long
test1 359.375
test2 296.875
我的结果
test1 593
test2 515还是你的快,但编译以后就完全一样了都是 30毫秒
a = 23
b = 23
If ((a And &H8000) < (b And &H8000)) Or (((a And &H8000) = (b And &H8000)) And ((a And &H7FFF) > (b And &H7FFF))) Then
MsgBox "a>b"
ElseIf a = b Then
MsgBox "a=b"
Else
MsgBox "a<b"
End If
怀疑楼上少打了一个 0
修正后的代码.
我这边速度都差不多.
Option Explicit
Private Declare Function timeGetTime Lib "winmm.dll" () As LongPrivate Const c_loop As Long = 100000000Dim i As Long
Dim t As LongPrivate Sub Form_Load()
Call test1
Call test2
Call test3
Call test4
End SubSub test1()
Dim bFirstIntMax As Boolean, int1 As Integer, int2 As Integer
int1 = -1
int2 = 800
t = timeGetTime
For i = 1 To c_loop '
' If (int1 < 0) Eqv (int2 < 0) Then
' bFirstIntMax = int1 > int2
' Else
' bFirstIntMax = int1 < int2
' End If
bFirstIntMax = (int1 > int2) And (int1 < 0) Eqv (int2 < 0)
Next MsgBox (timeGetTime - t)
End Sub
Sub test2()
Dim bFirstIntMax As Boolean
Dim int1 As Integer, int2 As Integer, l1 As Long, l2 As Long
int1 = -1
int2 = 800
t = timeGetTime
For i = 1 To c_loop '
l1 = CLng(int1) And &HFFFF&
l2 = CLng(int2) And &HFFFF&
bFirstIntMax = l1 > l2
Next MsgBox (timeGetTime - t)
End Sub
Sub test3()
Dim bFirstIntMax As Boolean
Dim a As Integer, b As Integer
a = -1
b = 800
t = timeGetTime
For i = 1 To c_loop
'bFirstIntMax = ((a And &H8000) < (b And &H8000)) Or ((Not (a Xor b) And &H8000) And (a > b))
bFirstIntMax = ((a And &H8000) < (b And &H8000)) Or ((a And &H8000) = (b And &H8000) And (a > b))
Next MsgBox (timeGetTime - t)
End SubSub test4()
Dim bFirstIntMax As Boolean
Dim a As Integer, b As Integer
Dim x1 As Integer, x2 As Integer
a = -1
b = 800 t = timeGetTime
For i = 1 To c_loop
x1 = a% And &H8000
x2 = b% And &H8000
bFirstIntMax = (x1 < x2) Or ((x1 = x2) And (a > b))
Next MsgBox (timeGetTime - t)
End Sub
i = -1
L = ivb的编译优化不会把L变成 65535的