Putting Your Own Hex On Your VBScript

Putting Your Own Hex On Your VBScript

  • Comments 18

Here's a fragment of an email I received last week:

bigValue = 4294967295
Wscript.Echo Hex(bigValue)
I would like this to display FFFFFFFF, but instead get the error "Overflow: bigValue

What's up with that?

The Hex function only works on numbers which fit into a four-byte signed integer. Since it's signed, you can have negative numbers in there. Negative numbers are represented in hex by their complement. Therefore, the number that produces FFFFFFFF is -1, not 4294967295. Therefore, the questioner is going to have to learn to live with disappointment -- you can't always get what you want.

But of course, you should feel free to write your own Hex function that has whatever semantics you prefer.  For instance, here’s one that will hexify an arbitrary double, and uses the innovation of a negative sign to indicate negative numbers. It uses some cheesy math tricks to repeatedly get the modulus of the number and shift the number down by a factor of 16 until there's nothing left:

Function MyHex(ByVal Number)
  Dim Sign
  Const HexChars = "0123456789ABCDEF"
  Sign = Sgn(Number)
  Number = Fix(Abs(CDbl(number)))
  If Number = 0 Then
    MyHex = "0"
    Exit Function
  End If
  While Number > 0
    MyHex = Mid(HexChars, 1 + (Number - 16 * Fix(Number / 16)), 1) & MyHex 
    
Number = Fix(Number/16)
  WEnd
  If Sign = -1 Then MyHex = "-" & MyHex
End Function

All I ask is that you not call the function "Hex", and thereby overwrite the existing Hex function, unless you really, really want to and know what you're doing.  Pulling shens like that can come back to haunt you later; I once spent about a day debugging an ASP page on MSN.com before I realized that it had it's own personal buggy implementation of InStr for some crazy reason, and someone else who modified the page did not realize that. 

  • > ...and thereby overwrite the existing Hex function...

    Huh? Coool. I've somehow managed to program in VBscript for 7 years now and remain completely unaware that I could override the built-in functions.

    It simply never occurred to me to try :)

    I think I'll go break something now and see what happens :)
  • > It simply never occurred to me to try :)

    That's probably because you're a sane, sensible programmer.
  • <p>
    (Slightly OT, maybe, but a lot of people don't know about this...)
    </p>
    <p>
    In JScript, the ability to override the methods of built-in objects can be extremely useful. For example, the Object class's toString method returns "[object Object]", which is less than informative; replacing it with a function that iterates over the properties of the instance on which it is invoked, building a usefully formatted string (e.g. as HTML), can be a valuable debugging tool.
    </p>
    <p>
    And, of course, you can redefine Math.PI as 3, to simplify your engineering calculations :-)
    </p>
  • Oops, sorry; didn't realise the HTML came out as source. Too many years posting to Slashdot :-)
  • It is cool, but it would be nicer to use prototype inheritance rather than blowing away the built-in OM.

    Why? Because it can play havoc with the compiler's ability to optimize, and with the code model of ASP.NET, which is why doing so is illegal when JScript .NET is in "fast mode". See my earlier post on JS.NET fast vs compatibiliy modes for details.

  • The problem is when you use JScript.NET in "fast mode" you totally loose the interesting features of ECMAScript like overriding build-in methods or adding new methods to build-ins objects etc...

    I understand the need for strictier mode which are easier to parse and better optimized, but for the life of me I don't see the point of making JScript a kind of class based language, if I need class I would rather use C#.

    I'm not ranting, I just don't understand the logic behind JScript.NET "fast mode" as I don't understand the logice behind ECMAScript 4 proposal.

    From a pragmatic point of view:

    - ECMAScript (ECMA-262) is the ECMA standard for prototype-based programming

    - C# (ECMA-334) is the ECMA standard for class-based programming


    if ECMAScript 4 (class-based) proposal is approved (and implemented as JScript.NET fast mode) it look like for me it will compete with C# and let an empty sit for prototype-based programming :(
    In the long run ECMAScript4 could simply die because its less powerfull than C#.

    from a programmer point of view:

    - E4X is more usefull than ECMAScript 4, it had been quickly approved because it made sens in the context of a langage which is prototype-based.
    new today: XML litterals, wouhou , that's a pretty good idea!

    - JScript.NET "fast mode" is better for optimization but it's worst for application scripting, who would want to produce script in almost the same syntaxe as C# ?
    (bigger nonsens in .NET when you can use the codeDOM to dynamically compile C# code)

    - if you compare JScript.NET "fast mode" and C#, the syntaxe is almost the same except minor difference, some behaviour are different (array etc..) but not that different, either C# or JScript.NET "fast mode" you have to think class-based.

    Not that class-based is no good, it's just that some people intentionnaly choose JScript (or ECMAScript at large) for its prototype-based features.

    Basically, prototype-based language reject the notion of class itself, with them you can ditch the abstract model of class and directly build objects, that allow you to have only 1 layer: the objects, and each one of these objects can evolve independantly outside of an abstract definition.

    "fast mode" don't allow me to do just that.
  • OK, here's a challenge for you then: how does JScript .NET work in ASP.NET without adding classes?
  • >The Hex function only works on numbers which
    >fit into a four-byte signed integer. Since
    >it's signed, you can have negative numbers in
    >there. Negative numbers are represented in
    >hex by their complement. Therefore, the
    >number that produces FFFFFFFF is -1, not
    >4294967295. Therefore, the questioner is
    >going to have to learn to live with
    >disappointment -- you can't always get what >you want.

    Why is it correct and appropriate for the Hex() function to burden the programmer with the details of its implementation in this manner?

    The Hex() function's job should be to simply return to the user the base-16 representation of the supplied base-10 number.

    Regardless of the range limitation imposed the use of four-byte signed integers, the Hex() function should *always* return -1 as the hexadecimal value of decimal -1 because *that is the correct answer*. FFFF or FFFFFFFF is not.

    If, for some reason, I wanted to know the complemet of a number, I can explicitly determine that when I need it, but that should not be the Hex() function's job.

    The programmer shoudn't be burdened with writing additional script just to obtain the answer that the inbuilt function *should* have provided itself.

    So what gives?




  • ok let's take this challenge :)

    in ASP.NET with JScript.NET fast mode
    as you explain in "Global State On Servers Considered Harmful"

    the class page are run in the same application domain, humm.. better rephrase that, the class astract page generate instances that may be run in the same application domain.

    on the contrary in ASP.NET with comptability mode or simply in ASP (not .NET), each JScript page are instance created in independant space.
    (kind of the same behaviour of WSF job package with WSH)

    I don't say that the actual ASP.NET model is flawed, on the contrary I found it great especially the code-behind feature, I'm just worried that this model force people to think class-based and when it comes to JSCript.NET I will choose C# and simply dump JScript.NET, just because C# is more suited in my opinion for class-based organization (and the fastest).

    What I found flawed with JScript.NET AND ECMAScript4 proposal is the change of nature to class-based, this is simply not logic for me.

    for example when writing JScript.NET in fast mode you got theses modifiers: public, private, protected, internal.

    for me the logic way to add modifiers to JScript would have been to follow ECMA-262 and use these: readonly, dontenum, dontdelete, internal.

    and now another challenge, do you see how these ECMA-262 inspired modifiers (readonly, dontenum ...) could have been used in JSCript.NET to add new method to build-in object prototype and in ASP.NET without generating race condition ?

    note: I don't say that to attack you, I have much respect for all the knowledge you share on your blog and sorry if my english bring confusion but it's not my natural language.
  • Eric K: Nowhere in your rant do you give any justification for the behaviour you desire other than "it's correct".

    We can have that argument if you'd like, but first we should have arguments like "if I calculate 2^54 + 1, I end up with 2^54, which is clearly incorrect", and "if I divide 1000000 / 3 I end up with an answer that is incorrect by several millionths", etc.

    After you have those arguments a few dozen times you realize that strict mathematical correctness is a whole lot harder to implement, and has very little practical efficacy for the majority of problems faced by typical programmers.

    Hex was implemented to show the underlying bits in an integer encoded as hex text simply because that's the most common usage case for developers. The vast majority of the time you're using the Hex function, you're doing it to, say, display an HRESULT. HRESULTs are never displayed as negative hex numbers, even though when interpreted as signed integers, they are.

    Is "FFFFFFFF" the correct answer? Who cares? It's the BY DESIGN answer. If you don't like that design because it doesn't meet your needs, well, you should have lobbied for that change when the function was first implemented back in, uh, 1992 or so. It's been like this for a decade.

    The real rant should be "why doesn't the documentation say all this?" And indeed, I'm irked that it doesn't. But that's why I'm here -- to get this stuff out on the internet.
  • Zwetan:

    The reason we need classes in JScript .NET to work with ASP.NET is because ASP.NETs very programming model is to generate a page class that extends and is extended by other page classes. It requires an inheritance model, not a prototype model.

    More generally though, we wanted to make JScript .NET a much richer language than C#. It has class-based and prototype based inheritance, first-class functions, closures, etc. But at the same time, we wanted to enable the programming-in-the-large features of languages like C# so that developers could have the best of both worlds -- leveraging their JScript skills while still being able to write large, typesafe programs.

    > What I found flawed with JScript.NET AND ECMAScript4 proposal is the change of nature to class-based, this is simply not logic for me.

    You can still use prototypes. We're adding stuff, not taking it away. Very few features don't work in fast mode.

    > for example when writing JScript.NET in fast mode you got theses modifiers: public, private, protected, internal. for me the logic way to add modifiers to JScript would have been to follow ECMA-262 and use these: readonly, dontenum, dontdelete, internal.

    You are misunderstanding the spec. You're confusing the metalanguage of the spec with the ECMAScript language it describes. (This is a very common mistake which I made myself on many occasions when first reading the spec!)

    dontenum, etc, are not modifiers for developers to put on objects; they are simply shorthand descriptions of how conforming implementations behave.
  • I'm with Eric K on this. Sure, FFFFFFFF as a long is -1, but if you're converting hex to dec or dec to hex, you're almost certainly not interested in signs. Perhaps an optional parameter to the Hex() function may have helped: Hex(Value As Long[, Signed As Boolean])

    I ran across a related aspect of this recently -- I was writing an simple encryption utility (in VBA of all things -- my company apparently can't afford to buy me VB) and wanted to work on QWords. However, all the built in math functions treat them as longs so they're signed, and a problem arises if there are four FFs in a row in the source file. In the end I had to do calculations on the individual bytes, as apparently FFFFFFFF - 1 is -2...

    So, either "fix" the Hex operations, or give me unsingned QWords! (On the other hand, I learnt an awful lot about optimising math routines which I would never have known beforehand. :)
  • I wish we could do this as a threaded newsgroup... microsoft.public.ericlippert.moderated, anyone? ;)
    Sidetracking from the hex issue...

    We discussed overriding internal functions in the newsgroups a few months ago and did come up with some unusual uses. Obviously not very useful ones since I don't recall any now. :)
    I do recall noting some more granular details, no doubt due to how the engine loads. For example, you CANNOT redefine a named function to be a Const without throwing an error. You CAN define it as a variable, but you have to explicitly dimension it first:

    Dim Mid: Mid = 95
    WScript.Echo Mid

    Out of curiosity, is there a reason for this? Or is it merely a side effect of Active Scripting language structure? I've seen people get themselves into trouble with this, but it's never been earth-shattering...
  • You mean, is there a reason why overriding a built-in function is legal in the first place?

    Not any good one as far as I know. AFAIK, that was an accident of how the name table was built. Probably the built-in functions should have been marked as non-assignable when the table is constructed.
  • in the philosophy to make JScript.NET a more richer language and from its ECMAScript nature
    why not allow at least to extend the build-in class ?

    like it has been discussed here:
    http://blogs.msdn.com/ericgu/archive/2004/07/01/171149.aspx

    this kind of feature is a good candidate for JScript.NET no ?

    modifying or adding to build-in objects in ECMAScript is an old problem
    http://groups.google.fr/groups?hl=fr&lr=&ie=UTF-8&c2coff=1&threadm=7b717m%24ag71%40secnews.netscape.com&rnum=9&prev=/groups%3Fq%3Dprototypes%2Bgroup:netscape.public.mozilla.jseng%26hl%3Dfr%26lr%3D%26ie%3DUTF-8%26c2coff%3D1%26selm%3D7b717m%2524ag71%2540secnews.netscape.com%26rnum%3D9

    sorry to have added so much Off Topic ot the original post but it's hard to refrain oneself to talk about such interesting JScript subject :)
Page 1 of 2 (18 items) 12