没有循环的整数到布尔/位数组

时间:2020-11-30 21:20:53

I have a number (say 5) which I would first like to convert to binary (101) and then split into an array of bits {1,0,1} or Booleans {True,False,True} in VBA

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

Is there a way to do this without looping?

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

I can convert to Binary without looping in my code with the worksheet formula as follows

我可以使用工作表公式转换为二进制而不用我的代码循环,如下所示

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

But I've been told that worksheet functions are very inefficient, and this one is particularly limited.

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

I'm not sure how to split into an array without looping through the digits with MID. Is there anything like strConv for numbers?

我不确定如何在不使用MID循环数字的情况下拆分成数组。有没有类似strConv的数字?

7 个解决方案

#1


5  

You could first convert the value to a "01" string with WorksheetFunction.Dec2Bin. Then replace each "0","1" with the code 0 or 1 and cast the result to a Byte array :

您可以先使用WorksheetFunction.Dec2Bin将值转换为“01”字符串。然后用代码0或1替换每个“0”,“1”并将结果转换为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

But Dec2Bin is limited to 511 and working with strings is rather expensive. So if your goal is to get the best performance, then you should use a loop to read each bit:

但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

#2


1  

I found this neat code on another question here at SO. Basically, you can be sure your string is ASCII due to the fact it's 1's and 0's.

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

What you do is you use

你做的是你用

Dim my_string As String

my_string =  CStr("your binary number")

To turn your binary number into a string

将二进制数转换为字符串

And then

接着

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

To split that string into an array where buff is your array

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

#3


1  

I think you've probably got everything you need above from other answers, but if you want a simple function that takes the decimal and returns the array..

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

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


0  

Invoking Application.Dec2Bin(n) isn't realy expensive, it only costs a late bound call. Use the function below to transform any integer into an arrays of bits:

调用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 will only contain 0 and 1 which are ASCII characters, so the split technique is perfectly valid.

p.s。:s只包含0和1,它们是ASCII字符,因此分割技术完全有效。

#5


0  

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


-1  

Please check this code if this is what you need: You can replace the the digit 5 by any cell value reference, this is just and example:

如果您需要,请检查此代码:您可以用任何单元格值引用替换数字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


-1  

Just change lngNumber value to your desired number

只需将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

Function DecToBin(ByVal varDecimalIn As Variant) As String

函数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

#1


5  

You could first convert the value to a "01" string with WorksheetFunction.Dec2Bin. Then replace each "0","1" with the code 0 or 1 and cast the result to a Byte array :

您可以先使用WorksheetFunction.Dec2Bin将值转换为“01”字符串。然后用代码0或1替换每个“0”,“1”并将结果转换为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

But Dec2Bin is limited to 511 and working with strings is rather expensive. So if your goal is to get the best performance, then you should use a loop to read each bit:

但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

#2


1  

I found this neat code on another question here at SO. Basically, you can be sure your string is ASCII due to the fact it's 1's and 0's.

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

What you do is you use

你做的是你用

Dim my_string As String

my_string =  CStr("your binary number")

To turn your binary number into a string

将二进制数转换为字符串

And then

接着

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

To split that string into an array where buff is your array

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

#3


1  

I think you've probably got everything you need above from other answers, but if you want a simple function that takes the decimal and returns the array..

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

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


0  

Invoking Application.Dec2Bin(n) isn't realy expensive, it only costs a late bound call. Use the function below to transform any integer into an arrays of bits:

调用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 will only contain 0 and 1 which are ASCII characters, so the split technique is perfectly valid.

p.s。:s只包含0和1,它们是ASCII字符,因此分割技术完全有效。

#5


0  

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


-1  

Please check this code if this is what you need: You can replace the the digit 5 by any cell value reference, this is just and example:

如果您需要,请检查此代码:您可以用任何单元格值引用替换数字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


-1  

Just change lngNumber value to your desired number

只需将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

Function DecToBin(ByVal varDecimalIn As Variant) As String

函数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