I'm trying to write a function that returns the number of bits set in a 32-bit integer in VBScript, it's just for practising the language. The function I've written so far looks okay, but I'm wondering if there was a simpler solution.
Function countBits(value)
Dim n : n = 0
Dim mask : mask = 1
Dim i
For i = 0 to 30
If (value And mask) > 0 Then
n = n +1
End If
Next
If (value And &h8000) then
n = n+1
End If
countBits = n
End Function
I found that there are no shift operators in VBScript and an overflow (Err.Number = 6
) if I iterate for 0 to 31, that's why I add the explicitly check of the MSB after the look.
Any solutions to improve (maybe generalize) this?
edit: removed the useless error handling part, as it's a remains of starting with 31 as an upper bound in the first (and at that time only) loop
-
\$\begingroup\$ Please do not edit the question, especially the code, after an answer has been posted. Changing the question may cause answer invalidation. Everyone needs to be able to see what the reviewer was referring to. What to do after the question has been answered. \$\endgroup\$pacmaninbw– pacmaninbw ♦2025年06月23日 11:33:24 +00:00Commented Jun 23 at 11:33
-
\$\begingroup\$ Thanks @pacmaninbw for the clarification. I only edited because my former editing mistake was not subject of the actual question. And also the answer only slightly touches this fact in a code comment... \$\endgroup\$Wolf– Wolf2025年06月23日 13:05:42 +00:00Commented Jun 23 at 13:05
1 Answer 1
According to information in VBScript Data Types MSDN article, a 32-bit integer is long
variant subtype.
However, the value &h8000
(decimal -32768
) seems to be a 16-bit integer
minimal value; it's hexadecimal &hFFFF8000
if converted to long
subtype (check Wscript.Echo Hex(&h8000)
.
This means that your function miscounts 1 additional bit for all long
values above 32767
i.e. above 16-bit integer
maximal value &h7FFF
.
To check the sign bit of a long
value correctly, use &h80000000
as follows:
Function countBits(value)
Dim mask : mask = 1
Dim i
countBits = 0 ' no need to use any auxiliary variable
For i = 0 to 30
If ( value And mask ) > 0 Then
countBits = countBits + 1
End If
mask = mask * 2 ' got lost due to your own edit Dec 11 '16 at 14:22
Next
If ( value And &h80000000 ) Then ' check the sign bit
countBits = countBits + 1
End If
End Function
Sample tests:
Wscript.Echo countBits(2^16) ' 1
Wscript.Echo countBits(2^30) ' 1
Wscript.Echo countBits(1) ' 1
Wscript.Echo countBits(-1) ' 32
Wscript.Echo countBits(-2) ' 31
Wscript.Echo countBits(-2147483648) ' 1
-
\$\begingroup\$ thanks so much sometimes I seem to be so blind for some important details, the off-by-one syndrome has so many faces this time I was off by one chunk of hexadecimal places. \$\endgroup\$Wolf– Wolf2017年07月31日 14:46:55 +00:00Commented Jul 31, 2017 at 14:46
-
1\$\begingroup\$ Again, thanks, only now I realize the error I introduced by my first edit, fixed. \$\endgroup\$Wolf– Wolf2025年06月23日 10:50:09 +00:00Commented Jun 23 at 10:50