How do you set, clear and toggle a single bit in JavaScript? - javascript

How to set, clear, toggle and check a bit in JavaScript?

To get a bit mask:
var mask = 1 << 5; // gets the 6th bit
To test if a bit is set:
if ((n & mask) != 0) {
// bit is set
} else {
// bit is not set
}
To set a bit:
n |= mask;
To clear a bit:
n &= ~mask;
To toggle a bit:
n ^= mask;
Refer to the Javascript bitwise operators.

I want to add some things (with thanks to #cletus)
function bit_test(num, bit){
return ((num>>bit) % 2 != 0)
}
function bit_set(num, bit){
return num | 1<<bit;
}
function bit_clear(num, bit){
return num & ~(1<<bit);
}
function bit_toggle(num, bit){
return bit_test(num, bit) ? bit_clear(num, bit) : bit_set(num, bit);
}

Get Bit
function getBit(number, bitPosition) {
return (number & (1 << bitPosition)) === 0 ? 0 : 1;
}
Set Bit
function setBit(number, bitPosition) {
return number | (1 << bitPosition);
}
Clear Bit
function clearBit(number, bitPosition) {
const mask = ~(1 << bitPosition);
return number & mask;
}
Update Bit
function updateBit(number, bitPosition, bitValue) {
const bitValueNormalized = bitValue ? 1 : 0;
const clearMask = ~(1 << bitPosition);
return (number & clearMask) | (bitValueNormalized << bitPosition);
}
Examples has been taken from JavaScript Algorithms and Data Structures repository.

I built a BitSet class with the help of #cletus information:
function BitSet() {
this.n = 0;
}
BitSet.prototype.set = function(p) {
this.n |= (1 << p);
}
BitSet.prototype.test = function(p) {
return (this.n & (1 << p)) !== 0;
}
BitSet.prototype.clear = function(p) {
this.n &= ~(1 << p);
}
BitSet.prototype.toggle = function(p) {
this.n ^= (1 << p);
}

Related

Javascript equivalent of Java's UUID class

In java, you can do something like
UUID id = UUID.fromString("eb66c416-4739-465b-9af3-9dc33ed8eef9");
long msb = id.getMostSignificantBits();
long lsb = id.getLeastSignificantBits();
System.out.println(msb + ", " + lsb);
// -1484283427208739237, -7281302710629372167
System.out.println(new UUID(msb, lsb));
// eb66c416-4739-465b-9af3-9dc33ed8eef9
This same example is referenced in another question which is pretty similar, so this would be a follow up. While in the related question problem of lsb, msb -> string was solved, I cannot find solution for reverse problem, string -> msb, lsb
The original solution was
function toUuidString(lsb, msb) {
return `${digits(msb >> 32n, 8n)}-${digits(msb >> 16n, 4n)}-${digits(
msb,
4n
)}-${digits(lsb >> 48n, 4n)}-${digits(lsb, 12n)}`
}
function digits(value, ds) {
const hi = 1n << (ds * 4n)
return (hi | (value & (hi - 1n))).toString(16).slice(1)
}
Now I'd like to have a function that takes in string and returns msb and lsb.
Following original questions' paths, I've discovered java source code and tried to do the equivalent, which would be:
function fromString(name) {
let components = name.split('-')
if (components.length !== 5) {
throw new Error(`Invalid UUID string: ${name}`)
}
for (let index = 0; index < 5; index++) {
components[index] = `0x${components[index]}`
}
let mostSigBits = Number.parseInt(components[0], 16)
mostSigBits <<= 16
mostSigBits |= Number.parseInt(components[1], 16)
mostSigBits <<= 16
mostSigBits |= Number.parseInt(components[2], 16)
let leastSigBits = Number.parseInt(components[3], 16)
leastSigBits <<= 48
leastSigBits |= Number.parseInt(components[4], 16)
return {
leastSigBits,
mostSigBits,
}
}
However, when I try to test this with something like:
const originalUuid = 'eb66c416-4739-465b-9af3-9dc33ed8eef9'
const parts = fromString(originalUuid)
const newUUid = toUuidString(
BigInt(parts.leastSigBits),
BigInt(parts.mostSigBits)
)
console.log('Original', originalUuid)
console.log('New', newUUid)
I do not get equivalent uuids. They have equivalent parts but some parts are missing
Original eb66c416-4739-465b-9af3-9dc33ed8eef9
New 00000000-4739-465b-ffff-ffffbefbeef9
Any ideas what went wrong?
Finally I found the problem - two codes were not strictly equivalent, java source code declared mostSigBits and leastSigBits as long, which cannot be represented in javascript, so we need to use BigInt.
To sum up my question and previous question, javascript equivalent for java's UUID operations would be:
string -> msb, lsb
function fromString(name) {
let components = name.split('-')
if (components.length !== 5) {
throw new Error(`Invalid UUID string: ${name}`)
}
for (let index = 0; index < 5; index++) {
components[index] = `0x${components[index]}`
}
let mostSigBits = BigInt(Number.parseInt(components[0], 16))
mostSigBits <<= 16n
mostSigBits |= BigInt(Number.parseInt(components[1], 16))
mostSigBits <<= 16n
mostSigBits |= BigInt(Number.parseInt(components[2], 16))
let leastSigBits = BigInt(Number.parseInt(components[3], 16))
leastSigBits <<= 48n
leastSigBits |= BigInt(Number.parseInt(components[4], 16))
return {
leastSigBits,
mostSigBits,
}
}
msb, lsb -> string (from the referenced question)
function toUuidString(lsb, msb) {
return `${digits(msb >> 32n, 8n)}-${digits(msb >> 16n, 4n)}-${digits(
msb,
4n
)}-${digits(lsb >> 48n, 4n)}-${digits(lsb, 12n)}`
}
function digits(value, ds) {
const hi = 1n << (ds * 4n)
return (hi | (value & (hi - 1n))).toString(16).slice(1)
}

Bitwise operation and arrow function return statement

I have a byte, and I want to increment bits left to the first bit by 1 (the context is a small Conway's Game of Life).
Example: 11 is 0000 1011:
I want to increment 101
5 + 1 = 6 is 110
reset the first bit to initial state
the byte is now 0000 1101 which is 13
Questions:
Is there a way to make addNeighbour proceed as a void method (I couldn't find a way to not return num)?
Is there a better way to perform addNeighbour operations :
const getBinaryRepresentation = (number) => {
let str = "";
for (let i = 7; i >= 0; i--) {
((number & (1 << i)) != 0) ? str += "1" : str += "0";
}
console.log(str)
}
let num = 5;
getBinaryRepresentation(num) // 0000 0101
const addNeighbour = (num) => {
const isAlive = num & 1;
const neighbours = num >> 1;
num = (neighbours + 1) << 1;
if (isAlive === 1) num |= (1 << 0)
return num;
}
num = addNeighbour(num);
getBinaryRepresentation(num) // 0000 0111
Is there a way to make addNeighbour proceed as a void method (I couldn't find a way to not return num)?
No. If you don't return the result, you cannot assign it back to num. And you cannot pass a reference to the let num (or any other) variable that the function should read from and store into.
Is there a better way to perform addNeighbour operations
Yes. Adding 1 at the second-least significant bit position is just the same as adding 2 at the least signification position. Replace your code with
num += 2;
Put in other terms,
(((num >> 1) + 1) << 1) | (num & 1)
≡ (((num >> 1) << 1) + (1 << 1)) | (num & 1)
≡ ((num & ~1) + (1 << 1)) | (num & 1)
≡ ((num & ~1) | (num & 1)) + (1 << 1)
≡ num + (1 << 1)
Since you can't have byRef on simple values in javascript you can't return void and change variable outside of the function.
You could optimize a little the function though, by reusing variables:
const getBinaryRepresentation = (number) => {
return console.log(number.toString(2).padStart(8, 0));
}
let num = 5;
getBinaryRepresentation(num) // 0000 0101
const addNeighbour = (num) => {
const isAlive = num & 1;
num >>= 1;
num = (num + 1) << 1;
return num | isAlive;
}
num = addNeighbour(num);
getBinaryRepresentation(num) // 0000 0111

Javascript get single bit

I have an integer and i want to check if a single bit is 0 or 1.
What is the best practise for doing that?
An example of what i'm doing at this moment:
const myInt = 8; // Binary in 32 Bit integer = 00000000000000000000000000001000
const myBit = myInt << 28 >>> 31; // 00000000000000000000000000000001
if (myBit === 1) {
//do something
}
But i think that this isn't the best methode for doing this.
Have you any better idea?
EDIT:
It is always the same bit i want to check, but the integer is different
myInt = 8+4; // 1100
n = 3;
(myInt >> n) & 0x1; // 1
n = 2;
(myInt >> n) & 0x1; // 1
n = 1;
(myInt >> n) & 0x1; // 0
n = 0;
(myInt >> n) & 0x1; // 0
general solution shifts your number by N bits to right, and applies bitmask, that leaves only last bit, all other are set to 0
I think you can use the bitwise AND
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators
my32Bit = 123414123;
twoBy7 = 128;
//check the 7th bit
if (my32Bit & twoBy7) {
// should return 1 if the 7thbit is 1
}
You could take the bit and a left shift << with bitwise AND & operator.
var value = 10,
bit;
for (bit = 0; bit < 4; bit++) {
console.log(bit, !!(value & (1 << bit)));
}

Extracting middle of string - JavaScript

I am trying to write an algorithm for this in JavaScript but I am getting a str.length is not a function...
function extractMiddle(str) {
var position;
var length;
if(str.length() % 2 == 1) {
position = str.length() / 2;
length = 1;
} else {
position = str.length() / 2 - 1;
length = 2;
}
result = str.substring(position, position + length)
}
extractMiddle("handbananna");
Because string length is not a function, it's a property.
function extractMiddle(str) {
var position;
var length;
if(str.length % 2 == 1) {
position = str.length / 2;
length = 1;
} else {
position = str.length / 2 - 1;
length = 2;
}
return str.substring(position, position + length)
}
console.log(extractMiddle("handbananna"));
Here is an another way to do this:
function extractMiddle(str) {
return str.substr(Math.ceil(str.length / 2 - 1), str.length % 2 === 0 ? 2 : 1);
}
// the most amazing
const getMiddle = s => s.substr(s.length - 1 >>> 1, (~s.length & 1) + 1);
// should return "dd"
console.log(getMiddle('middle'))
// >>> is an unsigned right shift bitwise operator. It's equivalent to division by 2, with truncation, as long as the length of the string does not exceed the size of an integer in Javascript.
// About the ~ operator, let's rather start with the expression n & 1. This will tell you whether an integer n is odd (it's similar to a logical and, but comparing all of the bits of two numbers). The expression returns 1 if an integer is odd. It returns 0 if an integer is even.
// If n & 1 is even, the expression returns 0.
// If n & 1 is odd, the expression returns 1.
// ~n & 1 inverts those two results, providing 0 if the length of the string is odd, and 1 if the length of the sting is even. The ~ operator inverts all of the bits in an integer, so 0 would become -1, 1 would become -2, and so on (the leading bit is always the sign).
// Then you add one, and you get 0+1 (1) characters if the length of the string is odd, or 1+1 (2) characters if the length of the string is even.
#author by jacobb
the link of the source is: https://codepen.io/jacobwarduk/pen/yJpAmK
That seemed to fix it!
function extractMiddle(str) {
var position;
var length;
if(str.length % 2 == 1) {
position = str.length / 2;
length = 1;
} else {
position = str.length / 2 - 1;
length = 2;
}
result = str.substring(position, position + length)
console.log(result);
}
https://jsfiddle.net/sd4z711y/
The first 'if' statement is to get the odd number while the 'else if' is to get the even number.
function getMiddle(s)
{
if (s.length % 2 == 1) {
return s.substring((s.length / 2)+1, (s.length / 2))
} else if (s.length % 2 == 0) {
return s.substring((s.length / 2)-1, (s.length / 2)+1)
}
}
console.log(getMiddle("handers"));
console.log(getMiddle("test"));
Here is my solution :-
function pri(word) {
if (!word) return 'word should have atleast one character';
let w = [...word].reduce((acc, val) => (val == ' ' ? acc : (acc += val)));
let res = '';
let length = word.length;
let avg = length / 2;
let temp = avg % 2;
if (temp == 0) {
res += word.charAt(avg - 1) + word.charAt(avg);
} else {
res += word.charAt(avg);
}
return res;
}
console.log(pri("Lime")); // even letter
console.log(pri("Apple")); // odd letter
console.log(pri("Apple is Fruit")); // String sequence with space
console.log(pri("")); // empty string
here is my solution
function getMiddle(s){
let middle = Math.floor(s.length/2);
return s.length % 2 === 0
? s.slice(middle-1, middle+1)
: s.slice(middle, middle+1);
}
function extractMiddle(s) {
return s.substr(Math.ceil(s.length / 2 - 1), s.length % 2 === 0 ? 2 : 1);
}
extractMiddle("handbananna");
str.length is a property. Just get rid of the parentheses. Example:
if (str.length == 44) {
length is a property of string, not a function. Do this instead:
str.length % 2 === 1
Also, use I suggest favoring === over ==
Since length is not a function, there is no need to use ().
function getMiddle(str) {
if(str.length % 2 === 0 ) {
return str.substr(str.length/2-1, 2);
} else {
return str.charAt(Math.floor(str.length/2));
}
}
console.log(getMiddle("middbkbcdle"));

Converting HashString from C to JS

I'm trying to convert this function from the Mozilla Firefox code base, it's called HashString. It calls a bunch of functions which are all in this file: https://dxr.mozilla.org/mozilla-central/source/mfbt/HashFunctions.h#294
So these are the C functions it calls:
static const uint32_t kGoldenRatioU32 = 0x9E3779B9U;
MOZ_WARN_UNUSED_RESULT inline uint32_t
HashString(const wchar_t* aStr)
{
return detail::HashUntilZero(aStr);
}
template<typename T>
uint32_t
HashUntilZero(const T* aStr)
{
uint32_t hash = 0;
for (T c; (c = *aStr); aStr++) {
hash = AddToHash(hash, c);
}
return hash;
}
MOZ_WARN_UNUSED_RESULT inline uint32_t
AddToHash(uint32_t aHash, A* aA)
{
/*
* You might think this function should just take a void*. But then we'd only
* catch data pointers and couldn't handle function pointers.
*/
static_assert(sizeof(aA) == sizeof(uintptr_t), "Strange pointer!");
return detail::AddUintptrToHash<sizeof(uintptr_t)>(aHash, uintptr_t(aA));
}
inline uint32_t
AddUintptrToHash<8>(uint32_t aHash, uintptr_t aValue)
{
/*
* The static cast to uint64_t below is necessary because this function
* sometimes gets compiled on 32-bit platforms (yes, even though it's a
* template and we never call this particular override in a 32-bit build). If
* we do aValue >> 32 on a 32-bit machine, we're shifting a 32-bit uintptr_t
* right 32 bits, and the compiler throws an error.
*/
uint32_t v1 = static_cast<uint32_t>(aValue);
uint32_t v2 = static_cast<uint32_t>(static_cast<uint64_t>(aValue) >> 32);
return AddU32ToHash(AddU32ToHash(aHash, v1), v2);
}
inline uint32_t
AddU32ToHash(uint32_t aHash, uint32_t aValue)
{
return kGoldenRatioU32 * (RotateBitsLeft32(aHash, 5) ^ aValue);
}
inline uint32_t
RotateBitsLeft32(uint32_t aValue, uint8_t aBits)
{
MOZ_ASSERT(aBits < 32);
return (aValue << aBits) | (aValue >> (32 - aBits));
}
And here is my js code:
function HashString(aStr, aLength) {
// moz win32 hash function
if (aLength) {
console.error('NS_ERROR_NOT_IMPLEMENTED');
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
} else {
return HashUntilZero(aStr);
}
}
function HashUntilZero(aStr) {
var hash = 0;
//for (T c; (c = *aStr); aStr++) {
for (var c=0; c<aStr.length; c++) {
hash = AddToHash(hash, aStr.charCodeAt(c));
}
return hash;
}
function AddToHash(aHash, aA) {
//return detail::AddU32ToHash(aHash, aA);
//return AddU32ToHash(aHash, aA);
//return detail::AddUintptrToHash<sizeof(uintptr_t)>(aHash, aA);
return AddUintptrToHash(aHash, aA);
}
function AddUintptrToHash(aHash, aValue) {
//return AddU32ToHash(aHash, static_cast<uint32_t>(aValue));
return AddU32ToHash(aHash, aValue);
}
function AddU32ToHash(aHash, aValue) {
var kGoldenRatioU32 = 0x9E3779B9;
return (kGoldenRatioU32 * (RotateBitsLeft32(aHash, 5) ^ aValue));
}
function RotateBitsLeft32(aValue, aBits) {
// MOZ_ASSERT(aBits < 32);
return (aValue << aBits) | (aValue >> (32 - aBits));
}
console.log(HashString('C:\Users\Vayeate\AppData\Roaming\Mozilla\Firefox\Profiles\aksozfjt.Unnamed Profile 10')); // should return 3181739213
This isn't working right, doing HashString('C:\Users\Vayeate\AppData\Roaming\Mozilla\Firefox\Profiles\aksozfjt.Unnamed Profile 10') should return to me 3181739213 however it's not. It keeps returning to me: -159266146140
Let's implement a more minimal C++ version first, which also dumps intermediate values which we can later compare.
#include <iostream>
#include <iomanip>
#include <stdint.h>
using namespace std;
static const uint32_t gr = 0x9E3779B9U;
template<typename T>
static uint32_t add(uint32_t hash, T val) {
const uint32_t rv = gr * (((hash << 5) | (hash >> 27)) ^ val);
cerr << dec << setw(7) << (uint32_t)val << " " << setw(14) << rv << " " << hex << rv << endl;
return rv;
}
int main() {
const auto text = string("C:\\Users\\Vayeate\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\aksozfjt.Unnamed Profile 10");
uint32_t rv = 0;
for (auto c: text) {
rv = add(rv, c);
}
cout << "Result: " << dec << setw(14) << rv << " " << hex << rv << endl;
}
Result: 3181739213 bda57ccd, so we're on the right track.
Now, for some Javascript:
GetNativePath returns an nsAutoCString aka. 8-bit string, by converting the internal 16-bit string to UTF-8.
Javascript does not actually know about 32-bit unsigned integers, just 32-bit signed integers, but there are some dirty tricks (mainly the >>> 0 "unsigned cast").
32-bit unsigned multiplication does not work, but we can actually implement that operation ourselves.
Properly escaping the backslashes \ in your test string also helps ;)
Putting these things together, I arrived at the following function, which seems to produce correct results.
/**
* Javascript implementation of
* https://hg.mozilla.org/mozilla-central/file/0cefb584fd1a/mfbt/HashFunctions.h
* aka. the mfbt hash function.
*/
let HashString = (function() {
// Note: >>>0 is basically a cast-to-unsigned for our purposes.
const encoder = new TextEncoder("utf-8");
const kGoldenRatio = 0x9E3779B9;
// Multiply two uint32_t like C++ would ;)
const mul32 = (a, b) => {
// Split into 16-bit integers (hi and lo words)
let ahi = (a >> 16) & 0xffff;
let alo = a & 0xffff;
let bhi = (b >> 16) & 0xffff
let blo = b & 0xffff;
// Compute new hi and lo seperately and recombine.
return (
(((((ahi * blo) + (alo * bhi)) & 0xffff) << 16) >>> 0) +
(alo * blo)
) >>> 0;
};
// kGoldenRatioU32 * (RotateBitsLeft32(aHash, 5) ^ aValue);
const add = (hash, val) => {
// Note, cannot >> 27 here, but / (1<<27) works as well.
let rotl5 = (
((hash << 5) >>> 0) |
(hash / (1<<27)) >>> 0
) >>> 0;
return mul32(kGoldenRatio, (rotl5 ^ val) >>> 0);
}
return function(text) {
// Convert to utf-8.
// Also decomposes the string into uint8_t values already.
let data = encoder.encode(text);
// Compute the actual hash
let rv = 0;
for (let c of data) {
rv = add(rv, c | 0);
}
return rv;
};
})();
let res = HashString('C:\\Users\\Vayeate\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\aksozfjt.Unnamed Profile 10');
console.log(res, res === 3181739213);
Might not be the most efficient implementation, but well, it works at least ;)
There is a simpler way
var file = new FileUtils.File('C:\\Users\\Vayeate\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\aksozfjt.Unnamed Profile 10');
file.QueryInterface(Ci.nsIHashable);
console.log(file.hashCode === 3181739213);

Categories

Resources