Fabulous Adventures In Coding
Eric Lippert is a principal developer on the C# compiler team. Learn more about Eric.
I've received some questions recently on how integer arithmetic works in VBScript, so I thought I might spend a few entries talking about some low-level bit twiddling topics. Here's one of the mails I got this morning:
There seems to be a limitation on the largest number that the VBScript "mod" operator works against. I was wondering if you could explain this limitation and how to overcome it. I have tried type casting using CDbl or CCur, but that does not seem to overcome the problem.
The mod operator, just to refresh your memory, returns the remainder of an integer division. So,
And indeed, the writer is correct. 2147483647 mod 2 returns 1, but 2147483648 mod 2 produces a type mismatch error. Since that's 2^31, you should be able to guess at what's going on here -- the mod operator only operates on values that can be fit into a 32 bit signed integer.
Let me describe precisely what we do. The
(Incidentally, the "integer division" operator in VBScript behaves pretty much exactly the same, as you'd expect given the obvious relationship between the two operators.)
VBScript provides modular arithmetic on signed 32/16 bit integers and unsigned bytes, and that's it. If you want to implement a modulus function that operates on currencies or floats or some other data type, you'll have to do the work yourself. How hard it is to write such a beast depends upon the desired range. We give you an operator that works over the range of a 32 bit signed integer, which seems like plenty to me. If you want something that works over the range of, say, a 53 bit signed integer, then this works:
Function MyMod(ByVal a, ByVal b) a = Fix(CDbl(a)) b = Fix(CDbl(b)) MyMod = a - Fix(a/b) * bEnd Function
This works just fine on 2147483648. In fact, it works well right up to 9007199254740990. But try
If you require integer arithmetic beyond 53 bits -- like, say, you're writing your own RSA implementation for some crazy reason, and need to do modular arithmetic on 1000+ bit integers -- then you'll need to use special techniques. Developing libraries that manipulate arbitrarily large numbers efficiently is definitely character-building, but I'd recommend that you do it in C or C# or some other hard-typed language designed for bit twiddling, not in VBScript.
Thanks for posting the workaround. We need to incorporate the ability to do these hex to dec and dec to hex conversions on very large numbers in order to convert MEID numbers (the new serial numbers issued by the FCC for cellular phones) in our database applications. Just one real world example of people playing around with great big numbers!
Old blog, but still quite helpful. Creating some IP range comparison math, it made sense (to me) to convert the dotted-octet address to decimal, then compare. I ran into the "VBScript runtime error: Overflow" error for addresses beyond 127.255.255.255 (2^31-1) using Mod. Since I needed Mod for addresses up to 255.255.255.255 (2^32-1), I was thwarted by 1 bit! Thankfully, the workaround was posted.