【问题标题】:Integer to boolean/bit array without looping整数到布尔/位数组而不循环
【发布时间】:2017-07-24 15:20:05
【问题描述】:

我有一个数字(比如 5),我想先将其转换为二进制 (101),然后在 VBA 中拆分为位数组{1,0,1} 或布尔值{True,False,True}

有没有办法在不循环的情况下做到这一点?

我可以使用以下工作表公式转换为二进制,而无需在我的代码中循环

myBinaryNum = [DEC2BIN(myDecInteger,[places])]

但有人告诉我,工作表功能非常低效,而且这个功能特别有限。

我不确定如何在不循环使用MID 的数字的情况下拆分为一个数组。有没有像strConv 这样的数字?

【问题讨论】:

    标签: arrays vba excel


    【解决方案1】:

    您可以先使用WorksheetFunction.Dec2Bin 将值转换为“01”字符串。 然后将每个 "0","1" 替换为代码 01 并将结果转换为 Byte 数组:

    Public Function ToBitArray(ByVal value As Long) As Byte()
      Dim str As String
      str = WorksheetFunction.Dec2Bin(value)                   ' "101"
      str = Replace(Replace(str, "0", ChrW(0)), "1", ChrW(1))  ' "\u0001\u0000\u0001"
      ToBitArray = StrConv(str, vbFromUnicode)                 ' [1, 0, 1]
    End Function
    

    但是Dec2Bin 仅限于 511 并且使用字符串相当昂贵。因此,如果您的目标是获得最佳性能,那么您应该使用循环来读取每一位:

    Public Function ToBitArray(ByVal value As Long) As Byte()
      Dim arr(0 To 31) As Byte, i As Long
      i = 32&
    
      Do While value
        i = i - 1
        arr(i) = value And 1
        value = value \ 2
      Loop
    
      ToBitArray = MidB(arr, i + 1)   ' trim leading zeros
    End Function
    

    【讨论】:

    • 新手问题,在你的第二个解决方案(带循环)中,i = 32**&** 的含义是什么,& 不是将前面的值声明为Long 类型,而是因为@ 987654331@ 已经声明了,而 32 只是一个数字,我不太确定这意味着什么?
    • 32& 表示将 32 用作Long32 单独用作Integer。当将值分配给变体并且需要它来保存Long 或避免操作溢出时,它很有用。在这里没关系,因为它会自动转换为i 的类型,即Long
    【解决方案2】:

    我在 SO 的另一个问题 here 上找到了这个简洁的代码。基本上,您可以确定您的字符串是 ASCII,因为它是 1 和 0。

    你所做的就是你使用

    Dim my_string As String
    
    my_string =  CStr("your binary number")
    

    将二进制数转换为字符串

    然后

    Dim buff() As String
    buff = Split(StrConv(my_string, vbUnicode), Chr$(0))
    ReDim Preserve buff(UBound(buff) - 1
    

    将该字符串拆分为一个数组,其中 buff 是您的数组

    【讨论】:

      【解决方案3】:

      我想你可能已经从其他答案中得到了你需要的一切,但是如果你想要一个简单的函数,它接受小数并返回数组..

      Function dec_to_binary_array(decNum As Integer)
          Dim arr() As String, NumAsString As String
          NumAsString = Application.Dec2Bin(decNum)
          arr = Split(StrConv(NumAsString, vbUnicode), vbNullChar)
          ReDim Preserve arr(UBound(arr) - 1)
          dec_to_binary_array = arr
      End Function
      

      【讨论】:

        【解决方案4】:

        调用Application.Dec2Bin(n) 并不昂贵,它只需要延迟绑定调用。使用以下函数将任何整数转换为位数组:

        Function Bits(n as long)
          Dim s As String: s = Application.Dec2Bin(n)
          Dim ar: ar = Split(StrConv(s, vbUnicode), vbNullChar)
          Bits = ar
        End Function
        

        p.s.:s 将只包含 01 ASCII 字符,因此拆分技术完全有效。

        【讨论】:

          【解决方案5】:
          Function d2bin(dec As Integer, bits As Integer) As Integer()
              Dim maxVal As Integer
              maxVal = 2 ^ (bits)-1
          
              If dec > maxVal Then Exit Function
          
              Dim i As Integer
              Dim result() As Integer
              ReDim result(0 To bits - 1)
          
              For i = bits - 1 To 0 Step -1
                  result(bits - i - 1) = -(dec > (2 ^ (i) - 1))
                  If result(bits - i - 1) Then dec = dec - (2 ^ i)
              Next i
          
              d2bin = result
          
          End Function
          

          【讨论】:

            【解决方案6】:

            如果这是您需要的,请检查此代码: 您可以将数字 5 替换为任何单元格值引用,这只是示例:

            Sub dectobinary()
            Dim BinaryString As String
            
            BinaryString = "5"
            
            tempval = Dec2Bin(BinaryString)
            
            MsgBox tempval
            
            End Sub
            
            
            Function Dec2Bin(ByVal DecimalIn As Variant) As String
            Dec2Bin = ""
            DecimalIn = Int(CDec(DecimalIn))
            Do While DecimalIn <> 0
                Dec2BinTemp = Format$(DecimalIn - 2 * Int(DecimalIn / 2))
                    If Dec2BinTemp = "1" Then
                        Dec2Bin = "True" & "," & Dec2Bin
                    Else
                        Dec2Bin = "False" & "," & Dec2Bin
                    End If
                DecimalIn = Int(DecimalIn / 2)
            Loop
            End Function
            

            【讨论】:

            • 这个解决方案有一个循环
            【解决方案7】:

            只需将 lngNumber 值更改为您想要的数字

            Public Sub sChangeNumberToBinaryArray()
            
            Dim strBinaryNumber As String
            Dim strBinaryArray()  As String
            Dim lngNumber As Long
            
                lngNumber = 5
            
                strBinaryNumber = DecToBin(lngNumber)
                strBinaryArray() = Split(strBinaryNumber, "|")
            
            End Sub
            

            函数 DecToBin(ByVal varDecimalIn As Variant) As String

            Dim lngCounter As Long
            
                DecToBin = ""
                varDecimalIn = Int(CDec(varDecimalIn))
                lngCounter = 1
                Do While varDecimalIn <> 0
                    If lngCounter = 1 Then
                        DecToBin = Format$(varDecimalIn - 2 * Int(varDecimalIn / 2)) & DecToBin
                        lngCounter = lngCounter + 1
                    Else
                        DecToBin = Format$(varDecimalIn - 2 * Int(varDecimalIn / 2)) & "|" & DecToBin
                        lngCounter = lngCounter + 1
                    End If
                    varDecimalIn = Int(varDecimalIn / 2)
                Loop
            End Function
            

            【讨论】:

            • 这个解决方案有一个循环
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-11-08
            • 2012-04-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-02-03
            • 2012-11-02
            相关资源
            最近更新 更多