Denis Ermolin
Denis Ermolin

Reputation: 5546

Number type and bitwise operations

I want to pack epoch milliseconds into 6 bytes but i have problem. Let me introduce it:

trace(t);
for (var i:int = 6; i > 0; i--) { 
    dataBuffer.writeByte(((t >>> 8*(i-1)) & 255));
    trace(dataBuffer[dataBuffer.length - 1]);
}

Output:

1330454496254
131
254
197
68
131
254

What i'm doing wrong?

Upvotes: 2

Views: 999

Answers (2)

Manish
Manish

Reputation: 3522

The Number type is an IEEE 754 64-bit double-precision number, which is quite a different format to your normal int. The bits aren't lined up quite the same way. What you're looking for is a ByteArray representation of a normal 64-bit int type, which of course doesn't exist in ActionScript 3.

Here's a function that converts a Number object into its "int64" equivalent:

private function numberToInt64Bytes(n:Number):ByteArray
{
    // Write your IEEE 754 64-bit double-precision number to a byte array.
    var b:ByteArray = new ByteArray();
    b.writeDouble(n);

    // Get the exponent.
    var e:int = ((b[0] & 0x7F) << 4) | (b[1] >> 4);

    // Significant bits.
    var s:int = e - 1023;

    // Number of bits to shift towards the right.
    var x:int = (52 - s) % 8;

    // Read and write positions in the byte array.
    var r:int = 8 - int((52 - s) / 8);
    var w:int = 8;

    // Clear the first two bytes of the sign bit and the exponent.
    b[0] &= 0x80;
    b[1] &= 0xF;

    // Add the "hidden" fraction bit.
    b[1] |= 0x10;

    // Shift everything.
    while (w > 1) {
        if (--r > 0) {
            if (w < 8)
                b[w] |= b[r] << (8 - x);

            b[--w] = b[r] >> x;

        } else {
            b[--w] = 0;
        }
    }

    // Now you've got your 64-bit signed two's complement integer.
    return b;
}

Note that it works only with integers within a certain range, and it doesn't handle values like "not a number" and infinity. It probably also fails in other cases.

Here's a usage example:

var n:Number = 1330454496254;

var bytes:ByteArray = numberToInt64Bytes(n);

trace("bytes:",
        bytes[0].toString(16),
        bytes[1].toString(16),
        bytes[2].toString(16),
        bytes[3].toString(16),
        bytes[4].toString(16),
        bytes[5].toString(16),
        bytes[6].toString(16),
        bytes[7].toString(16)
);

Output:

bytes: 0 0 1 35 c5 44 83 fe

It should be useful for serializing data in AS3 later to be read by a Java program.

Homework assignment: Write int64BytesToNumber()

Upvotes: 2

xxbbcc
xxbbcc

Reputation: 17327

I'm just guessing but I think your t variable is getting automatically converted to an int before the bit operation takes effect. This, of course, destroys the value.

I don't think it's possible to use Number in bit operations - AS3 only supports those with int-s.

Depending on how you acquire the value in t, you may want to start with 2 int-s and then extrat the bytes from those.

Upvotes: 2

Related Questions