What is the best way of implementing a bit array in JavaScript?
Advertisement
Answer
Here’s one I whipped up:
UPDATE – something about this class had been bothering me all day – it wasn’t size based – creating a BitArray with N slots/bits was a two step operation – instantiate, resize. Updated the class to be size based with an optional second paramter for populating the size based instance with either array values or a base 10 numeric value.
(Fiddle with it here)
JavaScript
x
163
163
1
/* BitArray DataType */
2
3
// Constructor
4
function BitArray(size, bits) {
5
// Private field - array for our bits
6
this.m_bits = new Array();
7
8
//.ctor - initialize as a copy of an array of true/false or from a numeric value
9
if (bits && bits.length) {
10
for (var i = 0; i < bits.length; i++)
11
this.m_bits.push(bits[i] ? BitArray._ON : BitArray._OFF);
12
} else if (!isNaN(bits)) {
13
this.m_bits = BitArray.shred(bits).m_bits;
14
15
}
16
if (size && this.m_bits.length != size) {
17
if (this.m_bits.length < size) {
18
for (var i = this.m_bits.length; i < size; i++) {
19
this.m_bits.push(BitArray._OFF);
20
}
21
} else {
22
for(var i = size; i > this.m_bits.length; i--){
23
this.m_bits.pop();
24
}
25
}
26
}
27
}
28
29
/* BitArray PUBLIC INSTANCE METHODS */
30
31
// read-only property - number of bits
32
BitArray.prototype.getLength = function () { return this.m_bits.length; };
33
34
// accessor - get bit at index
35
BitArray.prototype.getAt = function (index) {
36
if (index < this.m_bits.length) {
37
return this.m_bits[index];
38
}
39
return null;
40
};
41
// accessor - set bit at index
42
BitArray.prototype.setAt = function (index, value) {
43
if (index < this.m_bits.length) {
44
this.m_bits[index] = value ? BitArray._ON : BitArray._OFF;
45
}
46
};
47
48
// resize the bit array (append new false/0 indexes)
49
BitArray.prototype.resize = function (newSize) {
50
var tmp = new Array();
51
for (var i = 0; i < newSize; i++) {
52
if (i < this.m_bits.length) {
53
tmp.push(this.m_bits[i]);
54
} else {
55
tmp.push(BitArray._OFF);
56
}
57
}
58
this.m_bits = tmp;
59
};
60
61
// Get the complimentary bit array (i.e., 01 compliments 10)
62
BitArray.prototype.getCompliment = function () {
63
var result = new BitArray(this.m_bits.length);
64
for (var i = 0; i < this.m_bits.length; i++) {
65
result.setAt(i, this.m_bits[i] ? BitArray._OFF : BitArray._ON);
66
}
67
return result;
68
};
69
70
// Get the string representation ("101010")
71
BitArray.prototype.toString = function () {
72
var s = new String();
73
for (var i = 0; i < this.m_bits.length; i++) {
74
s = s.concat(this.m_bits[i] === BitArray._ON ? "1" : "0");
75
}
76
return s;
77
};
78
79
// Get the numeric value
80
BitArray.prototype.toNumber = function () {
81
var pow = 0;
82
var n = 0;
83
for (var i = this.m_bits.length - 1; i >= 0; i--) {
84
if (this.m_bits[i] === BitArray._ON) {
85
n += Math.pow(2, pow);
86
}
87
pow++;
88
}
89
return n;
90
};
91
92
/* STATIC METHODS */
93
94
// Get the union of two bit arrays
95
BitArray.getUnion = function (bitArray1, bitArray2) {
96
var len = BitArray._getLen(bitArray1, bitArray2, true);
97
var result = new BitArray(len);
98
for (var i = 0; i < len; i++) {
99
result.setAt(i, BitArray._union(bitArray1.getAt(i), bitArray2.getAt(i)));
100
}
101
return result;
102
};
103
104
// Get the intersection of two bit arrays
105
BitArray.getIntersection = function (bitArray1, bitArray2) {
106
var len = BitArray._getLen(bitArray1, bitArray2, true);
107
var result = new BitArray(len);
108
for (var i = 0; i < len; i++) {
109
result.setAt(i, BitArray._intersect(bitArray1.getAt(i), bitArray2.getAt(i)));
110
}
111
return result;
112
};
113
114
// Get the difference between to bit arrays
115
BitArray.getDifference = function (bitArray1, bitArray2) {
116
var len = BitArray._getLen(bitArray1, bitArray2, true);
117
var result = new BitArray(len);
118
for (var i = 0; i < len; i++) {
119
result.setAt(i, BitArray._difference(bitArray1.getAt(i), bitArray2.getAt(i)));
120
}
121
return result;
122
};
123
124
// Convert a number into a bit array
125
BitArray.shred = function (number) {
126
var bits = new Array();
127
var q = number;
128
do {
129
bits.push(q % 2);
130
q = Math.floor(q / 2);
131
} while (q > 0);
132
return new BitArray(bits.length, bits.reverse());
133
};
134
135
/* BitArray PRIVATE STATIC CONSTANTS */
136
BitArray._ON = 1;
137
BitArray._OFF = 0;
138
139
/* BitArray PRIVATE STATIC METHODS */
140
141
// Calculate the intersection of two bits
142
BitArray._intersect = function (bit1, bit2) {
143
return bit1 === BitArray._ON && bit2 === BitArray._ON ? BitArray._ON : BitArray._OFF;
144
};
145
146
// Calculate the union of two bits
147
BitArray._union = function (bit1, bit2) {
148
return bit1 === BitArray._ON || bit2 === BitArray._ON ? BitArray._ON : BitArray._OFF;
149
};
150
151
// Calculate the difference of two bits
152
BitArray._difference = function (bit1, bit2) {
153
return bit1 === BitArray._ON && bit2 !== BitArray._ON ? BitArray._ON : BitArray._OFF;
154
};
155
156
// Get the longest or shortest (smallest) length of the two bit arrays
157
BitArray._getLen = function (bitArray1, bitArray2, smallest) {
158
var l1 = bitArray1.getLength();
159
var l2 = bitArray2.getLength();
160
161
return l1 > l2 ? smallest ? l2 : l1 : smallest ? l2 : l1;
162
};
163
CREDIT TO @Daniel Baulig for asking for the refactor from quick and dirty to prototype based.