Convert an integer value to a 4-byte array

M

mprocopio

Fellow JavaScripters,

I am looking for code or implementation ideas for converting an integer
variable to a four-byte array. I'm porting some of my code from C#,
where I make use of their BitConverter utility class, but am still
feeling my way around a bit here with JavaScript.

The idea is that each of the four bytes that comprise an integer (I
presume numeric types in JavaScript are/can be made four bytes?) are
extracted, and then each of the four bytes are stored in the array...

Any help or pointers would be appreciated.


Thank you,

--Mike
 
M

mprocopio

"Make sure not to miss the class what ever your are in."

I can't tell if yours is a spam posting or not, but this last line is
interesting. I know plenty of students who post looking for homework
help. I'm not one of them--this is for a pet project of mine.

--Mike
Master of Science / Computer Science, University of Florida, 2002
 
D

Darren

well i've done a quicky in javascript and you might want to stick it in a
loop rather than the way i've done it but

bytes=new Array(3);
x=100000;
bytes[3]=x & (255);
x=x>>8
bytes[2]=x & (255);
x=x>>8
bytes[1]=x & (255);
x=x>>8
bytes[0]=x & (255);



document.write (bytes[0], " ");
document.write (bytes[1], " ");
document.write (bytes[2], " ");
document.write (bytes[3]);


HTH

Darren
 
D

Dr John Stockton

JRS: In article <[email protected]>, dated Thu,
11 Aug 2005 11:44:20, seen in David Given
(e-mail address removed) wrote:
[...]
The idea is that each of the four bytes that comprise an integer (I
presume numeric types in JavaScript are/can be made four bytes?) are
extracted, and then each of the four bytes are stored in the array...

Unfortunately, they're not... Javascript is defined to store its numbers as
8-byte IEEE floating-point types.

However, that format will hold the value of any 32-bit integer, whether
or not signed, exactly.
The only way you're going to be able to do this is to do modulos and
divisions in order to convert to base 256. Not particularly hard, but slow
and annoying.

Not the only way : shifts and masks will do it, and could be quicker,
FWIW.

I see one minor trap, probably affecting the different methods
differently : the sign bit. It may be best to extract it with
var NEG = (X<0) ; X = Math.abs(X)
and then OR or ADD it in to the top byte .... OTOH, maybe one can just
add 0x100000000 (2^32) and then convert, or add 2^31 and XOR the tip
with 0x80, or something like that. It rather depends on what you want.

Consider, for a start,
X = Math.pow(2,32)-Math.pow(2, 16) - 2*Math.pow(2, 8) - 4
A = []
J=4 ; while (J--) { A[J] = X & 0xFF ; X = X>>8 }
A // 255,254,253,252

You can get 6 bytes, and part of a seventh.
A few weeks ago someone posted wanting to convert a Javascript number into a
*floating point* byte array. Now, that was hard...

Not really : <URL:http://www.merlyn.demon.co.uk/js-misc0.htm#IEEE>.
 
M

mprocopio

Darren,

Thanks very much for your response. Your code does exactly what I was
looking for--excellent. I haven't tested it with all input, but at a
first cut, it's creating the arrays correctly.
From an optimization standpoint, any ideas on how to speed this up? It
will be called in a loop, 1000 times or so.

One idea I had is to not create the array in memory each time, but
actually pass it in as a parameter and reuse it. That should save 1000
dynamic array allocations (I'll do some metrics later).

If I know the integer is going to be bounded between 1 and 1000, one or
more of the chunks doesn't need to be calculated... I think only two
would need to be (255 * 255). So that should speed things up by two.

Also, what is the best format to perform bit operations with (the "&"
operator)? 255, or is a hex representation (0xFF or similar) better? In
this line, var a = x & (255), is the 255 being caster to a different
data type?
 
R

RobG

Darren,

Thanks very much for your response. Your code does exactly what I was
looking for--excellent. I haven't tested it with all input, but at a
first cut, it's creating the arrays correctly.

will be called in a loop, 1000 times or so.

I've 'function-ised' Darren's code below, it runs 10,000 'getBytes()' in
about 200ms (Firefox) or 220ms (IE) on a 2.4GH P4.
One idea I had is to not create the array in memory each time, but
actually pass it in as a parameter and reuse it. That should save 1000
dynamic array allocations (I'll do some metrics later).

You've gotta create the array sometime, and it takes very little time.
If I know the integer is going to be bounded between 1 and 1000, one or
more of the chunks doesn't need to be calculated... I think only two
would need to be (255 * 255). So that should speed things up by two.

For very large sets of numbers that are all within a range it maybe
worth it but the time spent calculating how many loops to do may take
longer than doing the loops.

There is an optimised version below called getBytes0 that stops looping
when x =0, it trims about 10% from the time but the array will have
undefined values for the missed loops - dealing with that may take back
the 10%.
Also, what is the best format to perform bit operations with (the "&"
operator)? 255, or is a hex representation (0xFF or similar) better? In
this line, var a = x & (255), is the 255 being caster to a different
data type?

Testing 255 vs 0xFF made no measurable difference, if there may be other
more meaningful optimisations.



<div id="msg2" style="font-weight:bold;"></div>
<p>Click reload to run again...</p>

<p>Enter a number and click elsewhere in the document</p>
<input type="text" onblur="
document.getElementById('msg').innerHTML =
getBytes(this.value).join('<br>');">
<p></p>
<div id="msg"></div>

<script type="text/javascript">

// Does exactly 4 loops
function getBytes( x ){
var bytes = [];
var i = 4;
do {
bytes[--i] = x & (255);
x = x>>8;
} while ( i )
return bytes;
}

// Stops looping when x = 0
function getBytes0( x ){
var bytes = [];
var i = 4;
do {
bytes[--i] = x&(255);
x = x>>8;
} while ( i && x > 0 )
return bytes;
}

/* Generate an array of numValues random integers
between 0 and 100,000, then do getBytes on them
and time it
*/

var j, sTime, fTime;
var numValues = 10000;
var randArray = [];
for ( j=0; j<numValues; j++) {
randArray[j] = (Math.random()*100000) | 0;
}

j = numValues;
sTime = new Date();
while ( j-- ) {
getBytes( randArray[j] )
}
fTime = new Date();

document.getElementById('msg2').innerHTML =
( 'Doing ' + numValues + ' values took ' + (fTime - sTime) + 'ms');

</script>
 
D

Darren

Darren,

Thanks very much for your response. Your code does exactly what I was
looking for--excellent. I haven't tested it with all input, but at a
first cut, it's creating the arrays correctly.

will be called in a loop, 1000 times or so.
one thing you could do is calculate the total value of each byte
respectivully instead of but shifting then mask off. ie

bytes=new Array(3);
x=16777217;
bytes[3]=x & (255);
bytes[2]=(x & (65280))/256;
bytes[1]=(x & (16711680))/65536;
bytes[0]=(x & (4278190080))/16777216;

processor wise i think this takes the same clock ticks as bitshifting but
i'm not sure of that.
One idea I had is to not create the array in memory each time, but
actually pass it in as a parameter and reuse it. That should save 1000
dynamic array allocations (I'll do some metrics later).

If I know the integer is going to be bounded between 1 and 1000, one or
more of the chunks doesn't need to be calculated... I think only two
would need to be (255 * 255). So that should speed things up by two.
if the parameter is never more than i thousdand then you only need two bytes
rather than four.
Also, what is the best format to perform bit operations with (the "&"
operator)? 255, or is a hex representation (0xFF or similar) better? In
this line, var a = x & (255), is the 255 being caster to a different
data type?
What i did above was to colculate the values of isolating each byte/ masking
it off but i origionally did it in hex but converted it to decimal because i
assumed that would remove any need to convert it processor wise i could be
thinking backward about this.

Let me know how it goes.

Darren
 
D

Dr John Stockton

JRS: In article <[email protected]>, dated Fri, 12
Aug 2005 04:53:34, seen in RobG
Testing 255 vs 0xFF made no measurable difference, if there may be other
more meaningful optimisations.

One might also test whether using global var XX = 255 and using XX
elsewhere is significantly better or worse.

And whether superfluous parentheses and inessential semicolons matter!



ISTM possible that an implementation of javascript might be intelligent
enough to keep the 32-bit results of logical operations in that form for
as long as possible, and whether one can find a cunning way of using
that.

It occurs to me that an IEEE Double can only hold genuine numbers
(including +0 -0), +Inf, -Inf, and very many NaNs. It cannot, however,
rightly hold undefined or null.

Therefore a Number object must have data storage apart from the IEEE
float (or cheat by re-using NaN-space, as javascript only knows one
NaN).

Therefore, it could store, in the 8-byte float-space, a 4-byte integer,
and store in its extra storage which of the two was in use.


My code for the conversion, and the reverse, is now at
<URL:http://www.merlyn.demon.co.uk/js-misc0.htm#I32>. However, it's
designed for display rather than speed.
 

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,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top