I'm using VBScript in ASP on IIS and I cannot seem to get the annoying error to go anyway so this makes debugging so much harder not to mention it does not tell me the exact error except the same error message so I can only assume what's wrong in my code.
My question is: Using the logical operators AND,XOR,NOT,OR in VBScript , is there a limit on the range to what the operands can be? I have implemented a bit shift right function and used the mod operator and I didn't notice until now that my function was causing the error.
My right shift function
function rshift(number,n)
'Shifts a number's bits n bits to the right
for i=1 to n
if number mod 2 = 0 then
number = number / 2
else
number = (number - 1) / 2
end if
next
rshift = number
end function
'Fails
rshift(1125899906842624,2)
I think for values larger than 2^32 ( or 31) - 1 that the operators do not work. Tried googling for the range of the operands but couldn't find anything helpful. I saw someone posted a topic about logical operators not working on large values but I can't seem to find that anymore.
Can someone verify this ?
Edit: Found a topic which gives more information on using the mod operator on signed 32 bit integers http://blogs.msdn.com/b/ericlippert/archive/2004/12/01/integer-arithmetic-in-vbscript-part-one.aspx
In VBScript there are several subtypes for integers including integer and long. VBScript will attempt to determine what type of value you are using and use the appropriate subtype.
Integer can store a value between -32,768 to 32,767 and long can store a value between -2,147,483,648 to 2,147,483,647. That value that you are using is greater than this and will result in an overflow.
You can use the VarType function to see what type your number is interpreted as. You may use Double to represent larger values.
This answer looks interesting. Maybe you can use it as part of your function.
Related
I want to write a program to convert hexadecimal numbers into their decimal forms without using a variable of fixed length to store the result because that would restrict the range of inputs that my program can work with.
Let's say I were to use a variable of type long long int to calculate, store and print the result. Doing so would limit the range of hexadecimal numbers that my program can handle to between 8000000000000001 and 7FFFFFFFFFFFFFFF. Anything outside this range would cause the variable to overflow.
I did write a program that calculates and stores the decimal result in a dynamically allocated string by performing carry and borrow operations but it runs much slower, even for numbers that are as big as 7FFFFFFFF!
Then I stumbled onto this site which could take numbers that are way outside the range of a 64 bit variable. I tried their converter with numbers much larger than 16^65 - 1 and still couldn't get it to overflow. It just kept on going and printing the result.
I figured that they must be using a much better algorithm for hex to decimal conversion, one that isn't limited to 64 bit values.
So far, Google's search results have only led me to algorithms that use some fixed-length variable for storing the result.
That's why I am here. I wanna know if such an algorithm exists and if it does, what is it?
Well, it sounds like you already did it when you wrote "a program that calculates and stores the decimal result in a dynamically allocated string by performing carry and borrow operations".
Converting from base 16 (hexadecimal) to base 10 means implementing multiplication and addition of numbers in a base 10x representation. Then for each hex digit d, you calculate result = result*16 + d. When you're done you have the same number in a 10-based representation that is easy to write out as a decimal string.
There could be any number of reasons why your string-based method was slow. If you provide it, I'm sure someone could comment.
The most important trick for making it reasonably fast, though, is to pick the right base to convert to and from. I would probably do the multiplication and addition in base 109, so that each digit will be as large as possible while still fitting into a 32-bit integer, and process 7 hex digits at a time, which is as many as I can while only multiplying by single digits.
For every 7 hex digts, I'd convert them to a number d, and then do result = result * (16^7) + d.
Then I can get the 9 decimal digits for each resulting digit in base 109.
This process is pretty easy, since you only have to multiply by single digits. I'm sure there are faster, more complicated ways that recursively break the number into equal-sized pieces.
In many algorithm i have seen people are using two different way to get middle point.
(LOW+HIGH)/2
LOW+(HIGH-LOW)/2
Mostly i have seen 2nd method for example in QuickSort. What is the best way to find middle between two number and why ?
It entirely depends on the context, but I'll make a case for case number 2 and explain why.
Let's first assume you go for case number 1, which is this:
(LOW + HIGH) / 2
This looks entirely reasonable, and mathematically, it is. Let's plug in two numbers and look at the results:
(12345 + 56789) / 2
The result is 34567. Looks OK doesn't it?
Now, the problem is that in computers it's not as simple as that. You also got something called data types to contend with. Usually this is denoted with such things as number of bits. In other words, you might have a 32-bit number, or a 16-bit number, or a 64-bit number, and so on.
All of these have what is known as a legal range of values, ie. "what kind of values will these types hold". An 8-bit number, unsigned (which means it cannot be negative) can hold 2 to the power of 8 different values, or 256. A 16-bit unsigned value can hold 65536 values, or a range from 0 to 65535. If the values are signed they go from -half to +half-1, meaning it will go from -128 to +127 for a 8-bit signed value, and from -32768 to +32767 for a signed 16-bit value.
So now we go back to the original formula. What if the data type we're using for the calculation isn't enough to hold LOW + HIGH ?
For instance, let's say we used 16-bit signed values for this, and we still got this expression:
(12345 + 56789) / 2
12345 can be held in a 16-bit value (it is less than 65536), same with 56789, but what about the result? The result of adding 12345 and 56789 is 69134 which is more than 65535 (the highest unsigned 16-bit value).
So what will happen to it? There's two outcomes:
It will overflow, which means it will start back at 0 and count upwards, which means it will actually end up with the result of 3598 (123456 + 56789) - 65536
It will throw an exception or similar, crashing the program with an overflow problem.
If we get the first result, then (12345 + 56789)/2 becomes 3598/2 or 1799. Clearly incorrect.
So, then what if we used the other approach:
12345 + (56789-12345)/2
First, let's do the parenthesis: 56789-12345 is equal to 44444, a number that can be held in a 16-bit data type.
Adding 12345 + 44444 gives us 56789, a number that can also be held in a 16-bit data type.
Dividing 56789 by 2 gives us 28934.5. Since we're probably dealing with "integers" here we get 28934 (typically, unless your particular world rounds up).
So the reason the second expression is chosen above the first is that it doesn't have to handle overflow the same way and is more resilient to this kind of problem.
In fact, if you think about it, the maximum second value you can have is the maximum legal value you can have for your data type, so this kind of expression:
X + (Y-X)
... assuming both X and Y are the same data type, can at most be the maximum of that data type. Basically, it will not have to contend with an overflow at all.
2nd method used, for avoid int overflow during computation.
Imagine, you used just 1-byte unsigned integer, so overflow happening if value reached 256. Imagine, we have low=100 and high=200. See computing:
1. (lo + hi) / 2 = (100 + 200) / 2 = 300 / 2; // 300 > 256, int overflow
2. lo + (hi - lo) / 2 = 100 + (200 - 100) / 2 = 150; // no overflow
There isn't a best one, but they are clearly different.
(LOW+HIGH)/2 causes trouble if the addition overflows, both in the signed and unsigned case. Doesn't have to be an issue, if you can assume that it never happens it's a perfectly reasonable thing to do.
LOW+(HIGH-LOW)/2 can still cause trouble with overflows if LOW is allowed to be arbitrarily negative. For non-negative input it's fine though. Costs an extra operation.
(LOW+HIGH) >>> 1 as seen in Java. For non-negative but signed input, overflow is non-destructive. The sign bit is used as an extra bit of space that the addition can carry into, the shift then divides the unsigned result by two. Does not work at all if the result is supposed to negative, because by construction the result is non-negative. For array indexes that isn't really a consideration. Doesn't help if you were working with unsigned indexes though.
MOV MID, LOW \ ADD MID, HIGH \ RCR MID in pseudo x86 asm, explicitly uses an extra bit of space and therefore works for all unsigned input no matter what, but cannot be used in most languages.
They all have their upsides and downsides. There is no winner.
The best way is dependent on what you're trying to accomplish. The first is clearly faster (best for performance), while the second one is used to avoid overflow (best for correctness). So the answer to your question is dependent on your definition of "best".
I'm working with process scheduling software called Appworx. In it, each process and subprocess can have an arbitrary number of "conditions", which if true, some conditional action is taken.
One of the possible conditional actions is a goto statement, where a plain integer is the label (each condition being numbered starting at 1). I'd like to use this feature to evaluate and run a few tasks in a loop, but you can only goto higher-numbered conditions (Don't ask me why... this seems to ruin most of the utility).
I have reason to believe that all of this is evaluated by Oracle on the backend. And having looked at the schema for Appworx, it appears that the goto labels are all NUMBER(12,0). I suspect that the logic that checks whether a label is lower than the current condition is something like:
where label > current_condition
So, if I were to supply a goto with a high enough value, I think it would cheat the checking and allow me to do simple loops. At least if Oracle used normal integers. Is it possible to overflow them, and what value would I use to overflow the value back to 1?
I suppose the Oracle version matters quite a bit, if so, it's 11g.
PS Also, if anyone would care to re-tag this for me, please add "appworx"
Oracle numbers are in fact floating point numbers with 40 decimal digit significand.
So, they can't be overflowed.
(10^40-1) is the maximal integer number which can be increased by 1.
proof
NUMBER(12,0) is a subtype of type NUMBER.
That is, it consists of NUMBER type and a restriction checker.
Well, that depends on your definition of 'overflow'. If you define 'overflow' as 'find a value n where n + 1 < n', then no, there's no such value. If you define 'overflow' as 'raises an exception', then yes, it's quite possible to perform an operation on a NUMBER(12,0) where an exception is raised.
Run the following:
DECLARE
n NUMBER(12, 0);
BEGIN
n := 999999999999; -- Twelve 9's
DBMS_OUTPUT.PUT_LINE('1 : n=' || n);
n := n + 1;
DBMS_OUTPUT.PUT_LINE('2 : n=' || n);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Exception: ' || SQLCODE || ' ' || SQLERRM);
END;
As you can see, the following exception is thrown when attempting to execute "n := n + 1":
ORA-06502: PL/SQL: numeric or value error: number precision too large
So it's quite possible to overflow a subtype of NUMBER. However, given that you're hoping to find a value n where n + 1 < n, I think you're out of luck.
And if you really want to provoke this behavior using the base NUMBER type, just execute
n := POWER(10, 126);
Of course, for truly nasty behavior in NUMBER you need to get it to produce a NaN (Not a Number):
n := 9999999999999999999999999999999999999999 * POWER(10, 125);
DBMS_OUTPUT.PUT_LINE('n=' || n);
produces
n=~
WTF?!? '~'? What the heck is '~'? Well, it appears that this is Oracle's way of printing a NaN. And the really fun part? Once you've got a NaN in a variable, any operation you perform on that variable will produce another NaN. Quietly. Silently. Without warning. Without recourse. Try:
DBMS_OUTPUT.PUT_LINE('n * 1234=' || n * 1234); -- produces n * 1234=~
DBMS_OUTPUT.PUT_LINE('n / 5678=' || n / 5678); -- produces n / 5678=~
Hey - have fun sweating your financials! :-)
In actual practice you're very unlikely to encounter this behavior, but it's the kind of thing you really need to be aware of - not only because encountering it can really ruin your month, but because (and you can count on this) next week the clueless guy in the cube by the bathroom is going to be asking about this - and you will now know all about it. (And you will now be able to rest easy, comfortable in the knowledge that this guy really is clueless and thus deserves to be parked in The Cube From Hell. I mean, you picked up on this on StackOverflow, right? So how hard can it be? :-)
Share and enjoy.
I once encountered a method of determining if a number x is a power of 2 by doing the following:
X&(x-1) followed by a 0 test, if the result is 0 then it means there is only one 1 bit in the number and that it is a power of 2. But the problem is it can't be used for signed int? I am just wondering if the only exception for a signed int is that it may be the signed bit that is the only one bit, if this is the case I could simply add another test and be done with it. Or does it have other exceptions that this method may not apply to a signed int. since I really wanna use it in java, I hope I can adopt it in some enhanced way. Thanks a lot.
It doesn't matter; just test for negatives. A power of a positive number is never negative, so you can safely say that any negative number given isn't a power of two.
In VB6, what is the likely cause of an Overflow error? I am using strings when it occurs.
Is it RAM, or hard-drive space? Or is it something internal to VB6?
I am going to take a stab in the dark here, some code would help as Hogan said. Typically overflow error occur with string when VB6 things it is dealing with integer or longs in math formulas and the results are too large for a integer or long to hold.
Depending on the nature of your formula you may get away from the problem by forcing the system to use the numbers as floating point by adding a '.0" at the end. Otherwise use the various Cxxx function to explicitly convert the numbers to a type that has a greater range.
The one thing you consider is that floating point are less precise than whole number integers so make sure you don't lose needed precision when you do the conversion.
Another 'stab', since no code is provided ...
The following will produce an overflow error:
Dim x as integer
x = len(longstring) 'longstring over 32,768 characters in length
Would cause an overflow error.
Dim x as long
x = len(longstring) 'longstring over 32,768 characters in length
Works fine.
Another example of an overflow from Microsoft Support here:
EDIT
A more subtle situation that can catch you off guard:
You attempt to use a number in a calculation, and that number is coerced into an integer, but the result is larger than an integer.
Dim x As Long
x = 2000 * 365 ' Error: Overflow
To work around this situation, type the number, like this:
Dim x As Long
x = CLng(2000) * 365