~ operator

C

chirs

Hi,

These 2 lines should be the same. But in IE5, they display 2 different numbers.
Why?

document.write((0xfffffff0).toString(10) + "<br>");
document.write((~0xf).toString(10) + "<br>");

Thank you.
 
L

Lee

chirs said:
Hi,

These 2 lines should be the same. But in IE5, they display 2 different numbers.
Why?

document.write((0xfffffff0).toString(10) + "<br>");
document.write((~0xf).toString(10) + "<br>");

Because numbers are not stored as 32 bit integers.
 
L

Lasse Reichstein Nielsen

These 2 lines should be the same.

Says who? :)
But in IE5, they display 2 different numbers. Why?

Because
0xfffffff0 != ~0xf
The value of 0xfffffff0 is 4294967280.
The value of ~0xf = -16.
The comparison is made on Javascript numbers which are not equal.

Javascript integers are not 32 bit numbers, they are actually IEEE
double-precission floating point numbers. The bit-level operations
work by first converting the number to 32-bit integers (skipping
decimals and taking modulo 2^32 on the integer part). The result is then
treated as a *signed* 32-bit two's complement number.

That is why ~0xf = -16. First 15 is converted to a 32-bit number. Then
its bits are inverted, giving the bit-pattern 0xfffffff0. This,
interpreted as a *signed* 32-bit number is -16.

Since you do no bit operations on 0xfffffff0, it is not interpreted as
a signed 32-bit value, just as some positive number.

If you put the ~ on 0xfffffff0 instead, the two lines would give the
same (15). If you interpreted 0xfffffff0 as a 32-bit signed number,
it would also give the same (~~0xfffffff0 == ~0xf).
document.write((0xfffffff0).toString(10) + "<br>");
document.write((~0xf).toString(10) + "<br>");

(And ~ is the one's complement (bitwise negation) in Javascript, like
in most C-syntax based languages, and Number.prototype.toString takes
an argument in Javascript 1.1+, JScript 2+, and ECMAScript)

/L
 
R

Richard Cornford

VK said:
toString() method doesn't take arguments

<quote ECMA 262 3rd edition>
15.7.4.2 Number.prototype.toString (radix)
If radix is the number 10 or undefined, then this number value
is given as an argument to the ToString operator; the resulting
string value is returned.

If radix is an integer from 2 to 36, but not 10, the result is
a string, the choice of which is implementation-dependent.

The toString function is not generic; it throws a TypeError
exception if its this value is not a Number object. Therefore,
it cannot be transferred to other kinds of objects for use as
a method.
~ is not a part of number notation

<quote ECMA 262 3rd edition>
11.4.8 Bitwise NOT Operator ( ~ )
The production UnaryExpression : ~ UnaryExpression is evaluated
as follows:
1. Evaluate UnaryExpression.
2. Call GetValue(Result(1)).
3. Call ToInt32(Result(2)).
4. Apply bitwise complement to Result(3). The result is a
signed 32-bit integer.
5. Return Result(4).
Are you sure you are studying JavaScript and not something else?

Looks like JavaScript to me.
If you are not just joking, you may want to look on something like
http://www.devguru.com/Technologies/ecmascript/quickref/javascript_
intro.html

You are recommending that as an accurate and up to date source of
information on JavaScript?

Richard.
 
F

Fox

chirs said:
Hi,

These 2 lines should be the same. But in IE5, they display 2 different numbers.
Why?

document.write((0xfffffff0).toString(10) + "<br>");
document.write((~0xf).toString(10) + "<br>");

Bitwise operations are broken in IE...always have been... the sign bit
is not supported.
 
L

Lasse Reichstein Nielsen

Fox said:
Bitwise operations are broken in IE...always have been... the sign bit
is not supported.

Can you expand on that? E.g., show something that fails in IE?
As far as I can see, they are working fine in IE6, and I would be
surpriced if even Microsoft could botch something as simple as bitwise
operations.

/L
 
V

VK

Looks like I'm a dinosaur with my 1.x-1.2 JavaScript

I did not realize the amount of changes in later versions.
 
L

Lasse Reichstein Nielsen

VK said:
Looks like I'm a dinosaur with my 1.x-1.2 JavaScript

Well, the ~ operator was in Javascript 1.0, and the toString method of
numbers with an optional radix existed in Netscape 3 (Javascript
1.1?). :)

/L
 
F

Fox

Lasse said:
Well, the ~ operator was in Javascript 1.0, and the toString method of
numbers with an optional radix existed in Netscape 3 (Javascript
1.1?). :)
yeah -- but it's still better to roll your own -- toString(radix)
(16/hex, 2/binary) insists on prefixing a '-' sign for numbers in which
the MSB is set... it's better to roll your own.
 
F

Fox

Lasse said:
Can you expand on that? E.g., show something that fails in IE?
As far as I can see, they are working fine in IE6, and I would be
surpriced if even Microsoft could botch something as simple as bitwise
operations.
[I'm a "Mac-centric" programmer]

Don't be so surprised -- IE is full of these little annoyances [botched?
-- I don't think so -- it serves to derail the competition now that IE
is the majority (modern case in point: the padding/margin box model)].

As long as I can remember, the Mac version of IE has had problems with
the MSB in bitwise operations. Seems to me that there were problems with
earlier pc versions as well. I no longer have versions of IE prior to
IE5.5 for the PC -- maybe someone could check out former versions. I
stopped checking the pc version since as long as there were still
problems with the Mac version, it didn't make sense writing special case
workarounds -- the browser sniff wasted any performance gain that might
have existed using bitwise.

In IE5 (at least on the Mac) bit #31 (MSB) is completely ignored and/or,
incorrect results are returned.

try to set the high bit with |, e.g.: 0x0 | 0x80000000;

IE5 returns 0x7FFFFFF;

as does 0x00000001 | 0x80000000; //same result (in 5.0)! both, of
course, are completely wrong.

(You also cannot test for "negativity" with & 0x80000000.)

Either way, if you program for the general internet population (and
actually take Macs into consideration -- very few pc-only programmers
do) using bitwise operators on the MSB is out of the question and since
IE is no longer being developed for the Mac platform (although it is
still in heavy use) it will *always* have these problems with bitwise operations.

On the plus side, there is little need for bitwise operations in
JavaScript since there is no real speed benefit as there is in compiled
languages. So, instead of testing the "sign" bit with & 0x80000000, it's
just as easy, and perhaps more efficient *in javascript* to simply use a
less than zero test (x < 0). You can still use an integer as a boolean
set, just don't expect to get the use of all 32 bits on a Mac.
 
L

Lasse Reichstein Nielsen

Fox said:
yeah -- but it's still better to roll your own -- toString(radix)
(16/hex, 2/binary) insists on prefixing a '-' sign for numbers in which
the MSB is set... it's better to roll your own.

The MSB (most significant bit) doesn't really exist in Javascript
numbers. Javascript numbers are double precission floating point
numbers. The relevant bit is the sign bit, and I can't see any reason
*not* to add a prefix minus if the number is negative.

If that is a problem, run the number through Math.abs first.

Some implementations even allow toString(radix) on non-integer numbers.
In IE6 and Mozilla, (-16.03125).toString(2) == "-10000.00001" . In Opera,
a non-integer argument is converted in base 10. In Netscape 4, the result
is "/0000". I have no idea why.

/L
 
L

Lasse Reichstein Nielsen

Fox said:
[I'm a "Mac-centric" programmer]

Don't be so surprised -- IE is full of these little annoyances [botched?
-- I don't think so -- it serves to derail the competition now that IE
is the majority (modern case in point: the padding/margin box model)].

Don't get me started :)
But their implementation of ECMAScript has always been one of the better.
I haven't seen any attempts from them to break ECMAScript. They embrace and
extend as usual, giving us JScript, but I would normally trust the core
ECMAScript to be correct.

In IE5 (at least on the Mac) bit #31 (MSB) is completely ignored and/or,
incorrect results are returned.

try to set the high bit with |, e.g.: 0x0 | 0x80000000;

IE5 returns 0x7FFFFFF;

Indeed, that is incorrect. The correct result is -0x80000000 (-2147483648).
I.e., (0x0 | 0x80000000).toString(16) == "-0x80000000" , which is what
IE 6 gives me.
as does 0x00000001 | 0x80000000; //same result (in 5.0)! both, of
course, are completely wrong.

Yes, this should be -0x7FFFFFFF.
(You also cannot test for "negativity" with & 0x80000000.)

You shouldn't be able to.
Both
2147483648 & 0x80000000
and
-2147483648 & 0x80000000
should give the result -2147483648.

Still, inside the range [-2147483648 ... 2147483647], it should work.

It sounds like IE-Mac is indeed broken in this respect.

/L
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top