标题的表达可能不准确,实际的意思:
大家知道,VB中的integer是有符号数,即最高位是表示符号的,最高位为1为负数。现在我在解析DDS图像格式,就遇到了这样的问题,在某一个步骤中,我需要比较两个占用2个字节的整数的大小,原始的C代码可以用C中的无符号整数的数据类型读取这两个数,然后直接用>运算符比较,而VB中只能用先把这两个字节的数读入两个integer变量中,但是这个时候VB中的>运算符返回的结果就不一定的正确的结果了。一个简单的做法就是用copymemory把integer变量拷贝到long 变量后在比较,但是这个在大循环中就会成为影像速度的瓶颈。我还没有仔细考虑这个问题的优化方法,先发个帖子让大家帮忙先想想把。

解决方案 »

  1.   

    Option ExplicitSub Main()
        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
      

  2.   

    图像处理,本身就不该用integer,用byte。图像就是一系列的rgba值或是对调色板的索引值操作,应该用byte类型吧。
    可能我没理解你意思。
      

  3.   

     l1 = CLng(v1) And &HFFFF&
     l2 = CLng(v2) And &HFFFF&
    实质还是借用long类型来比较。
      

  4.   

    方法1、直接用long去取就能直接比较了。方法2、用两个byte的字节数组去取。之后自己写一段很简单的if语句比较一下就可以了。首先比较高位,如果相同就再比较一下低位。估计效率不会慢。
      

  5.   

    我想你的意思是该双字节数值在内存里表达的是个无符号整数, 而在VB中无法直接放到integer类型中吧(超过32767就表达成了负数,所以影响了比较结果)?我猜想这个数本身也是通过内存复制得到的,或者是一个数组的元素.所以才会造成无法直接赋值给long型,因为不同类型数组赋值地址无法对其.能否用一个byte型的二维数组呢? Dim Bits(1,N) as byte
    要比较第I个数的大小,先比Bits(1,I),如果一样大,再比Bits(0,I)
    不知道这样能否解决楼主的问题.
      

  6.   

    除了位运算,copymemory就应该是最快的了
      

  7.   

    1.直接字符串大小比较  If Hex(integer1) > Hex(integer2) Then
      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  注: 这样可能还是影响速度你可以测一测, 这是在不转换数据类型的情况下想出的办法, 如果要转换数据类型, 我想一样要影响效率!
    大伙一起再想一想吧...
      

  8.   

    性能瓶颈不仅是无符号数,还有VB本身的数组(比指针慢了N多倍),不妨用C++ SDK编写比较函数,然后得到ASM代码,再在VB里内嵌ASM代码来提高速度。
      

  9.   

    只要能比就行,总之内部类型转换比 CopyMemory 快。 
      

  10.   

    为什么不直接把这两个字节 读入到4个字节中的Long 变量中呢?
      

  11.   

    为什么不直接把这两个字节 读入到两个 Long 变量中呢?除非后面还要用到integer类型,否则就用不着 integer --> long 转换了。
      

  12.   

    我想楼主的这个问题应该是有前提限制的,如我前面所说,如果只是简单想象成将一个无符号int类型赋给VB的Long型,那么请想一想这前面的那个无符号int数是怎么来的呢? 
    直接从一个VB的integer类型变量来的,这当然是不可能,否则就不存在楼主的问题了.
    那么这个无符号int数据就很可能是从内存或文件上来的.
    再想一下,如果只有一个或几个数,那么即使用copymemory或类型转换也不麻烦,并且也慢不到哪里去.
    那么剩下的可能就只能是内存或文件中的一大段双字节数据了.因为套上大循环之后copymemory的速度肯定是很低的.
    直接将这段无符号int数据复制到VB的long型数组也是有问题的,因为元素长度不同存在对齐的问题.
    所以我的想法是复制到一个二维byte数组内,不过后来想想直接复制到一维的byte数组性能更好,反正只要记得每2个元素代表原来的一个数就行了.
    但是如果这个int除了比较大小,还要进行拆分的话,那转化为byte有可能并不会带来任何好处,(比如555,或565的颜色分量分离),因为还是要合并到一个long型变量里再用除法拆开,反而更麻烦了.
    归根结底,因为缺乏足够的基本数据类型和真正的位操作,VB在处理这样数据时往往需要在性能上做一些妥协的.
    最后祝楼主早日出关啊,给VB版增添生气.
      

  13.   

    其实基本上就是楼上说的这个意思
    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,那读取的数据就不是正确的了。
      

  14.   

    最近一直都在专注于图像格式的解码和编码啊,越陷越深了,搞玩这种格式就又想搞另外一种。目前基本搞定
    BMP\JPG\PNG\GIF\TIF\ICO\WMF\EMF\PSD\PNM\TGA\PCX\WBM\XWD\DCM\FIT\IFF\SGI\XBM\RAS\DDS\PBT 这22种图像格式。
      

  15.   

    565格式的要得到各个分量还是可以直接方便的用integer类型的,比如加入color变量是一个你读入565格式的图像的一个像素的值,则其分量可由下面的算式计算:
    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)
      

  16.   

    9楼的说法有道理
    在不转换数据类型的情况下实现比价 -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
      

  17.   

    打错 符号
      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
      

  18.   

    NND 航班延误8小时,才回到家,在去机场的路上想到的优化方式在不转换数据类型的情况下实现比较  -1 最大  0最小
    if (int1 > int2) And (int1 < 0) Eqv (int2 < 0)  then代替 
    int1 --> lon1 '类型转换
    int2 --> lon2
    if lon1 > lon2 then
      

  19.   

    如果一定要用VB的话,只能转换成Long后再比较了,不过还是建议使用其它语言实现再嵌入到VB中。
      

  20.   

    请给出你的测试例子,我这里转 Long 型更快。
    '窗体上加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
      

  21.   

    看来是 比较方式不同Sub test1()
        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
      

  22.   

    25楼:你的测试代码非功能部分影响太大了。
    1)在模块头部定义
    Private i As Variant '等同于你现在不声明变量的方式'
    test1 359.375 
    test2 484.375 
    2)在模块头部定义
    Private i As Long
    test1 359.375 
    test2 296.875 
      

  23.   

    有理 ,老鸟的电脑比我的好 dim i  as long后
    我的结果
    test1 593
    test2 515还是你的快,但编译以后就完全一样了都是 30毫秒
      

  24.   

    long就行了,以前在vb中处理64位整数,自己写嫌烦,直接用vc写一个dll让vb调用了,好省心。
      

  25.   

    '试试这个方法,测试比上面的快一倍左右    Dim a As Integer, b As Integer
        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
      

  26.   

    For i = 1 To 10000000 
    怀疑楼上少打了一个 0
      

  27.   

    刚刚看错..嘿嘿
    修正后的代码.
    我这边速度都差不多.
    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
      

  28.   

    定义两个long类型,在要比较的时候, long = ingeter 然后再比较,我想vb的编译优化会完美的搞定这个问题
      

  29.   

    dim L as long , i as  ingeter
    i = -1 
    L = ivb的编译优化不会把L变成 65535的