From: Csaba Gabor on
On Dec 2, 6:46 pm, mr_unreliable <kindlyReplyToNewsgr...(a)notmail.com>
wrote:
> Csaba Gabor wrote:
> > I'd like to determine the number of bits (the position
> > of the highest on bit) in a negative number (say -1)
> > without using knowledge of its type.
>
> The "brute force" way would be to "shift left" one bit
> at a time, until you hit your 1-bit.
>
> Problem is, you can't shift left in script.  There are
> a number of shifting functions written in VB, but they
> require calling the system api.

You can shift left in VBScript - Just multiply the
number by 2. The problem is that if you have
2^14 (as an integer) and you shift left by 1 it becomes
a long so that the sign does not go negative. And
while this isn't a problem with positive numbers, it is
a problem with the negatives, since the sign keeps
getting extended. In other words, as you keep
multiplying your bit selector by 2, it will eventually
turn from an integer to a long. When you and or
xor it with the number being tested, that in turn will
turn into the type matching the selector, extending
any leading 1s for negative numbers. Nevertheless,
this is the approach that I've used.

The highest bit position for a negative number is given
by the highest bit position for a -1, which can be
trivially givien if one presumes to know how many
bytes it takes to represent a given type. But that's
what I didn't want to tie myself to.

> Most scripters abhor calling the system api, and so
> your best bet is to wait around for a more knowledgable
> person to come along with a "pure script" solution.
>
> cheers, jw
From: Csaba Gabor on
On Dec 2, 7:27 pm, Tom Lavedas <tlave...(a)gmail.com> wrote:
> On Dec 2, 12:46 pm, mr_unreliable <kindlyReplyToNewsgr...(a)notmail.com>
> wrote:
>
> > Csaba Gabor wrote:
> > > I'd like to determine the number of bits (the position
> > > of the highest on bit) in a negative number (say -1)
> > > without using knowledge of its type.
>
> > The "brute force" way would be to "shift left" one bit
> > at a time, until you hit your 1-bit.
>
> > Problem is, you can't shift left in script.  There are
> > a number of shifting functions written in VB, but they
> > require calling the system api.
>
> > Most scripters abhor calling the system api, and so
> > your best bet is to wait around for a more knowledgable
> > person to come along with a "pure script" solution.
>
> > cheers, jw
>
> JScript has SHIFT operators, so the old trick of using JScript in VBS
> will work ...
>
> wsh.echo ShiftRight(clng(-1) and &h7fffffff&, 30)
>
> Function ShiftRight(arg, n)
>   with createobject("htmlfile")
>     .write "<script>var a=" & arg & ">>" & n & ";</script>"
>     ShiftRight = .parentWindow.a
>   end with
> end function
>
> Function ShiftLeft(arg, n)
>   with createobject("htmlfile")
>     .write "<script>var a=" & arg & "<<" & n & ";</script>"
>     ShiftLeft = .parentWindow.a
>   end with
> end function

Hi Tom,
VBScript can do JS style of shifting just fine, I think:
For shift left, just multiply by 2 (or add the number to itself),
which should work for both positive and negative integers.

For shift right, the situation is a bit more complicated.
It amounts to a floor operation after division by a power of 2:
x >> n is:
x AND (-1 XOR 2^n-1) / 2^2
Though the type of notation I've used may cause the type
of the result to change (since 2^n produces a double, for
example).

> I also propose ANDing the number (converted to a Long - 32 bit -
> number) with a mask that zeros the minus sign bit.  Then the other

This is what I'm trying to avoid. You have presumed to know
where the high bit is already (in the case of negative numbers).

> bits can be tested.  The shift that first returns a value of zero is
> the most significant bit (I didn't bother to show the test loop).

> BTW, your shift nomenclature seems backward to me.  I guess you were
> thinking of shifting the mask and not the number.  However, starting
> from the MSB end would still seem most efficient and would still shift
> the mask to the right, not the left wouldn't it?

Your conclusion is only valid if you presume you know where the
high bit must be (in which case you will get a trivial answer for
negative numbers, but no clear win for positive numbers). However,
the bit shifting approach from right to left must have a basis for
termination, which is the hard part, I think.
From: Csaba Gabor on
On Dec 2, 11:17 pm, "Paul Randall" <paulr...(a)cableone.net> wrote:
> "mr_unreliable" <kindlyReplyToNewsgr...(a)notmail.com> wrote in message
>
> news:u1ybAb3cKHA.5156(a)TK2MSFTNGP04.phx.gbl...
>
>
>
>
>
> > Csaba Gabor wrote:
> >> I'd like to determine the number of bits (the position
> >> of the highest on bit) in a negative number (say -1)
> >> without using knowledge of its type.
>
> > The "brute force" way would be to "shift left" one bit
> > at a time, until you hit your 1-bit.
>
> > Problem is, you can't shift left in script.  There are
> > a number of shifting functions written in VB, but they
> > require calling the system api.
>
> > Most scripters abhor calling the system api, and so
> > your best bet is to wait around for a more knowledgable
> > person to come along with a "pure script" solution.
>
> If the task must be done without using "knowledge of its type", then double
> precision floats might be involved, which could be a lot of bits that don't
> shift nicely

Only integers (but not integer types are presumed).
When I posed the question, I didn't have a solution - this
problem has been bugging me since around the time of
http://groups.google.com/group/microsoft.public.vb.general.discussion/browse_frm/thread/1732616a8f0a7d02
But I realized that I had made the conditions a bit
too harsh, and really meant that one shouldn't presume
knowledge of any specific type (as opposed to knowing
its type). So I programmed up a solution based on
detecting a type change. Still, I was not happy with
this, so in writing this up I have produced the following
which has worked for all my test cases, and about which
I am less unhappy (improvements welcome):

MsgBox HighBitPos (0) '-1
MsgBox HighBitPos(27) '4
MsgBox HighBitPos(16384) '14
MsgBox HighBitPos(2^14) '14
MsgBox HighBitPos(32768) '15
MsgBox HighBitPos(2^15) '15
MsgBox HighBitPos(-1) '15
MsgBox HighBitPos (-&1&) '15
MsgBox HighBitPos(&H10FFFF) '20
MsgBox HighBitPos(-&HFFFF&) '31

Function HighBitPos(n)
HighBitPos = -1
On Error Resume Next
Dim bit, typ: bit=1: typ=typename(n)
While typ=typename(n) AND n<>0
HighBitPos = HighBitPos + 1
If (n AND bit) Then n = n XOR bit
If n = -n OR bit=-n Then exit Function
bit = 2*bit
Wend
' HighBitPos = HighBitPos & " " & typ
End Function


Csaba Gabor from Vienna
That on error is there because of the last
case. When missing, it will die on the first If.