64-битная битовая маска и javascript

В настоящее время я борюсь с проблемой javascript, где у меня есть 62-битная битовая маска, которую следует использовать в качестве фильтра.

Я использовал фрагмент отсюда, но в некоторых случаях не могу заставить его работать. Как выполнить побитовое И в javascript для переменных, длина которых превышает 32 бита?

function testBitmask(fd, filterMask){
                            var a = fd;
                            var b = filterMask;

                            var w = 4294967296; // 2^32

                            var aHI = a / w;
                            var aLO = a % w;
                            var bHI = b / w;
                            var bLO = b % w;

                            var aAll = (aHI & bHI) * w;
                            var bAll = (aLO & bLO);

                            var retVal = (aAll + bAll) == filterMask;
                            console.log("retVal:",retVal)
                            return retVal;
}

Я не понимаю, почему testBitmask (2147483648,2147483648) возвращает false, то есть 2 ^ 31. 2 ^ 32 => верно. 2 ^ 33 => верно.

Здесь bAll становится отрицательным, поэтому я предполагаю переполнение 32-битного int, ideas?


person Max Melcher    schedule 10.06.2015    source источник
comment
Побитовые операторы преобразуют числа в 32-битные целые числа.   -  person Felix Kling    schedule 10.06.2015


Ответы (1)


Если в javascript все числа представляют собой 64-битные числа с плавающей запятой и нет 64-битных целых чисел, вы не можете ожидать определения a и b (или fd и filtermask) с такой точностью без ошибок округления.

Попробуйте определить объект, который инкапсулирует 64-битный целочисленный тип.

В качестве примера вы можете посмотреть на реализацию js-ctype, созданную Mozilla MDN:

https://developer.mozilla.org/en-US/docs/Mozilla/js-ctypes/js-ctypes_reference/Int64

и в частности

https://developer.mozilla.org/en-US/docs/Mozilla/js-ctypes/Using_js-ctypes/Working_with_data#64-bit_integers.

Их объекты Int64 и UInt64 не предоставляют никаких методов для выполнения арифметических операций, но вы можете выделить старшие и младшие 32-битные части и выполнить с ними математические вычисления, а затем снова объединить их.

Простой пример кода, использующий вместо этого типизированные массивы:

bitMask = function(high = 0x0,low = 0x0) {
    this.bm = new Uint32Array(2);

    if (arguments.length === 0 ) {
        this.bm[0] = 0x0;
        this.bm[1] = 0x0;
    }  else if (arguments.length === 2 && typeof arguments[0] === "number" && typeof arguments[1] === "number") {
        this.bm[0] = arguments[1];
        this.bm[1] = arguments[0];
    }

    this.bwAND = function(filter) {
        result = new bitMask();
        result.bm[0] = this.bm[0] & filter.bm[0];
        result.bm[1] = this.bm[1] & filter.bm[1];
        return result;
    }

    this.bwOR = function(filter) {
        result = new bitMask();
        result.bm[0] = this.bm[0] | filter.bm[0];
        result.bm[1] = this.bm[1] | filter.bm[1];
        return result;
    }

    this.bwXOR = function(filter) {
        result = new bitMask();
        result.bm[0] = this.bm[0] ^ filter.bm[0];
        result.bm[1] = this.bm[1] ^ filter.bm[1];
        return result;
    }

    this.bwNOT = function() {
        result = new bitMask();
        result.bm[0] = ~this.bm[0];
        result.bm[1] = ~this.bm[1];
        return result;
    }

    this.bwEQUALS = function(b){
        return (this.bm[0] == b.bm[0]) && (this.bm[1] == b.bm[1]);
    }

    this.toString = function() {
        var zeroes = "00000000000000000000000000000000";
        var strH = this.bm[1].toString(2);
        var zerH = zeroes.substr(0,32-strH.length);
        var strL = this.bm[0].toString(2);
        var zerL = zeroes.substr(0,32-strL.length);
        return zerH + strH + zerL + strL;
    }

}

Вы можете использовать это так:

var a = new bitMask(0x0FEDCBA9,0xFF00FF00);
var b = new bitMask(0x12345678,0x0000FFFF);
var c = b.bwAND(a);
var d = b.bwOR(a);
var e = b.bwXOR(a);
var f = b.bwNOT();
var g = b.bwEQUALS(a);

Результаты:

    a = 0000111111101101110010111010100111111111000000001111111100000000
    b = 0001001000110100010101100111100000000000000000001111111111111111
a & b = 0000001000100100010000100010100000000000000000001111111100000000
a | b = 0001111111111101110111111111100111111111000000001111111111111111
a ^ b = 0001110111011001100111011101000111111111000000000000000011111111
   ~b = 1110110111001011101010011000011111111111111111110000000000000000
(a == b)? = false
person Bob__    schedule 10.06.2015