Bit counter

I’m still working on this idea, but haven’t come up with an “elegant” solution

Problem : given an Integer Value, return an array of the counts of bits

Example :
given 11110000 would return (4,4) … 4 1’s and 4 0’s
given 11001110 would return 2,2,3,1

assumption : skip “leading” zeros, so count starts with first significant digit

return value can be a delimted string, or an integer array

  Dim s As String=Bin(n)
  Dim c As String="1"
  Dim a() As Integer
  Dim x As Integer
  While s<>""
    While Left(s,1)=c
      x=x+1
      s=Mid(s,2)
    Wend
    a.append x
    If c="1" Then
      c="0"
    Else
      c="1"
    End If
  Wend 

gotta be a better way

oh… and for how I’m gonna use this… RegEx won’t be an option…

No responses yet… hmm
I see your code assembles a string of 1s and 0s
But ultimately you want an array of the bit counts

I dont think there is a much more elegant method to get the bitruns

I wouldnt turn it into a string first, myself.
I’d probably hit the bits one by one.

What would have been cool is a feature I used to use in GFA basic, where an integer or memroyblock could be treated directly as an array of bits
So the integer was immediately equal to bit(32)

as it stands, maybe a loop that goes to each bit in turn, and writes the ‘count so far’ as soon as the state changes

[code]dim orig as integer = 78257
dim bittest as integer
dim lastval as integer = 9
For x as integer = 32 downto 1
bittest = x ^2
//compare this bitwaiseand to the orig value
//if same as the previous test, then increment a counter,
//else add to the array, set last = to this value, and reset the counter

next[/code]

GFA Basic… wow… I used that on an ATARI ST something or other

Thats the one.
A much earlier cross platform Basic.
I used it for Atari ST, Amiga 500/1200 , and 386 level PCs
There was a Windows version later too.

I just checked… someone is keeping it alive and it still produces 32 bit code that works in Windows 10.
Color me impressed…

Anyway, hows your bitrun counter coming along?

AMIGA here :slight_smile:

I did use GFA Basic on Atari ST and Amiga. Centuries ago…

for now I’m using the code from OP, once I get to the “tuning” stage I may change it

To tweak your code a bit, turn the string into an array and iterate over that, rather than proliferating strings via left and mid.

Dim s As String=Bin(n)
Dim sa() as string = Split(s, "")
For i = 0 to ubound(sa)
...

Also, remember to reset x

a.append x
x = 0

Just count bits
No conversion to string required

  dim i as Uint64 = &h8000000000000000
  dim last as integer = 0
  dim startCounting as boolean
  dim result() as integer
  do 
    dim this as integer = bitwise.BitAnd(v, i)
    if this <> 0 then startCounting = true
    if startCounting then
      select case true
      case this <> 0 and last = 0 // switched from 0 to 1
        result.append 1
      case this = 0 and last <> 0 // switched from 1 to 0
        result.append 1
      else // still 1 or still 0
        result(result.ubound) = result(result.ubound) + 1
      end 
    end if
    last = this
    i = bitwise.ShiftRight(i,1,64)
  loop until i = 0

now that is a neat approach… I like it… Norman, I take back everything I’ve said about you… well ok… SOME of it :slight_smile:

Assuming you don’t have to worry about sign bits and that you have a lot of data to churn through one idea would be to split the number into bytes, having set up a table on program start with all 256 byte values. The table entries just need the required 0/1 splits then, if the byte is < 128 it starts with 0, else 1. You can then use the byte value ( 0-255) to do a subscript lookup on the table and concatenate the 0/1 splits how you need.

Then again, Norman’s answer looks really clever.

( Unless I am just being stupid again :wink: )

Nope… don’t care about sign bits… its actually to create a dot/dash pattern for use with line drawing… the method requires an array , but I want to use an single integer to store the property

bitwise.BitAnd(v, i)

… thats what I was getting at with

bittest = x ^2 //compare this bitwaiseand to the orig value

The bitwise.bitand() is much more elegant… good spot Norm…

I wondered if that was what it was for.
Do you envisage a use for more than 4 elements in the array?

eg 3, 6,4,12

I store dash patterns for (PDF) lines too, but I find it overkill for my needs to use anything more than ‘this amount on, this amount off, repeat’
So my storage (in XML) is a string holding eg 3,5
(there are lots of other ways I could do it, or course)

If your patterns can be restricted to no more than 4 changes, you could store the patterns as simple strings of 4 bytes, (which actually is the same size as an integer anyway).
eg BGBR … take the ASCII value of each letter in turn and subtract 65 from each.