What is a ^ b and (a & b) << 1? - javascript

I was doing this question in leetcode.
Request:
Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -.
I can't understand the solution it gave
Could someone explain how this getSum function works?
Here is the answer in JS:
var getSum=function(a,b) {
const Sum = a^b; //I can't understand how those two line's code can
const carry = (a & b) << 1; //get the sum
if(!carry) {
return Sum
}
return getSum(Sum,carry);
};
console.log(getSum(5,1));

It's basically replicating the half-adder
Adding 2 bits A and B produces 2 outputs: a sum and a carry bit like below
╔═══════╤═════════════╗
║ Input │ Output ║
╠═══╤═══╪═══════╤═════╣
║ A │ B │ carry │ sum ║
╟───┼───┼───────┼─────╢
║ 0 │ 0 │ 0 │ 0 ║
╟───┼───┼───────┼─────╢
║ 1 │ 0 │ 0 │ 1 ║
╟───┼───┼───────┼─────╢
║ 0 │ 1 │ 0 │ 1 ║
╟───┼───┼───────┼─────╢
║ 1 │ 1 │ 1 │ 0 ║
╚═══╧═══╧═══════╧═════╝
From the table we get the logic for the outputs: carry = A and B, sum = A xor B
XOR is also called a carry-less add operator, and represented by ⊕ with the + symbol inside
So the snippet above is working like this
const Sum=a^b; // sum = a xor b = a ⊕ b
const carry=(a&b)<<1; // carry = 2*(a and b), since we carry to the next bit
if(!carry){
return Sum; // no carry, so sum + carry = sum
}
return getSum(Sum,carry); // a + b = sum + carry
So a^b adds each bit in a and b simultaneously, leaving the non-carry sum of a and b in Sum. Then we have to add carry to the carry-less sum to get the final result, since we have only a half-adder instead of a full-adder which does a + b = a ⊕ b + carry
See also
Adding two numbers without + operator (Clarification)
What is the best way to add two numbers without using the + operator?
adds two numbers without using + or any arithmetic operators
Adding two numbers without using the addition operator

Let's learn by example. Imagine that a = 3 and b = 5
In binary notation they are a = 0011 and b = 0101
XOR:
a^b is XOR operator. When compare two bits it returns 0 if they are same and 1 if they are different. 01^10 => 11
So when we're doing a^b result will be 0110.
AND + SHIFT
a&b performs logical AND operation. It returns 1 only when a = b = 1.
In our case the result is 0001
<< shifts it(adds 0 on the right side) and result became 0010 which sets carry variable true. (only 0000 will be false).
Next iterations:
Everything repeats but now a = 0110 and b = 0010 (Sum and carry from last execution)
Now a^b = 0100 and (a&b)<<1 = 0100
Repeating again.
Now a^b = 0000 and (a&b)<<1 = 1000
And again.
Now a^b = 1000 and (a&b)<<1 = 0000. Now carry is finally false. And we're returning 1000 which is decimal 8.
Everything worked fine since 3+5=8

int result = p ^ q; // XOR Operator, + without carry 0+0=0, 0+1=1+0=1, 1+1=0
int carry = (p & q) << 1; // Left Shift, 1+1=2
if (carry != 0) {
return getSum(result, carry);
}
return result;
Start By p=5,q=6. Then the XOR would be,
0101
0110
------
0011
So, XORing results in (0011) which is actually 3 in decimal. Then ANDing p and q we get,
0101
0110
-------
0100
We get 4 (100 in binary) by ANDing 5 & 6, now if we left shift this value by 1, we get
0100<<1=1000
So we get 8 (1000 in binary) after first recursion.As the result (carry variable) isnt zero, lets recursion again by xor value and carry value.
getSum(3, 8);
So, doing the first XORing we get,
0011
1000
-------
1011
The XORing this time yielded in 11 (1011 binary),so we perform the AND now,
0011
1000
-------
0000
We get all ZERO for ANDing 3 and 8, so this time the left shift operator also results in ZERO, as we have no 1 here which may give us a value by left shifing zeroes.
As the carry variable is now Zero, we come to the end of recursion and the XORed value will be the Sum, which is 11 (1011 in Binary).
Hope you get the working of the procedure. You can learn more by learning bitwise operation, as its the way the machine do the arithmatic operations.

^ is XOR, a bitwise operation. On a single bit, the rules are 0 ^ 0 = 0, 0 ^ 1 = 1, 1 ^ 0 = 0, and 1 ^ 1 = 0, and you simply extend perform it on corresponding bits when dealing with multi-bit values. The name is short for "exclusive or", and comes from the fact that A ^ B is 1 if and only if either A or B is 1, not both. But, it's more interesting to talk about its other name, ⊕. ⊕ is + but slightly different. You'll notice that the rules for ⊕ are similar to the rules for addition: 0 + 0 = 0, 0 + 1 = 1, 1 + 0 = 1, and 1 + 1 = 10. ⊕ is +, except 1 ⊕ 1 = 0; that is, ⊕ is +, except without carrying. This holds for multiple bits: 011 + 001 = 100, because you carry a 1 out of the ones place into the twos place, and then carry a 1 again into the fours place. Then, 011 ⊕ 001 = 010, because you just don't carry.
Now, when doing real addition, when do you carry? In binary, the answer is very simple: you carry a 1 into the next place when there are two 1s in a given place. This is easily understood as a bitwise AND, &. 1 & 1 = 1, and 0 otherwise. For 011 + 001, addition without carrying gives 011 ⊕ 001 = 010, and we can tell we need to carry a 1 out of the ones place because 011 & 001 = 001. The shifting in (a & b) << 1 turns a number "where do I need to carry from?" into "where do I need to add carries?": (011 & 001) << 1 = 010; I need to add a carry bit in the twos place.
So, in getSum, we want to know a + b. We compute the addition without carrying with a ^ b, and we find where we need to add carry bits with (a & b) << 1. Now, we just need to add those two together. Well, we already have a function for adding numbers together; it's called getSum. So, we basically just write function getSum(a, b) { return getSum(a ^ b, (a & b) << 1); }, except we make sure to short-circuit if there is nothing to carry, saving us from infinite recursion.

Related

How does bitwise operation work on Booleans?

I came across this challenge on Edabit and couldn't work out this bitwise operation solution.
notNotNot = (a,b) => !!(a%2 >> b)
The challenge:
//Something which is not true is false, but something which is not not true is true!
//Create a function where given n number of "not", evaluate whether it's true or false.
//Examples:
notNotNot(1, true) ➞ false
// Not true
notNotNot(2, false) ➞ false
// Not not false
notNotNot(6, true) ➞ true
// Not not not not not not true
I did some research that that operator:
Shifts right by pushing copies of the leftmost bit in from the left, and let the rightmost bits fall off.
That I reckon I understood (e.g. 5 >> 1 same as 0101 >> 1 which evaluates to 0010), but I can't see how that works with a boolean? I know true evaluates to 1 and false to 0.
The function you gave does not satisfy the challenge. Right shifting will not do what is asked for. For example, your notNotNot(6,true) is false, not true when put through your function.
Your question is about bitwise operation on a boolean though. Since operators like >> and << work on integers, Javascript first converts the boolean value to an integer. So true becomes 1 and false becomes 0. To see this you can shift by zero:
console.log("true is",true >> 0)
console.log("false is", false >> 0)
So bitwise operation on booleans is really just bitwise operation on either 0 or 1.
Using !! is a handy way to convert anything into a boolean. It takes anything that would be considered equivalent to false (such as 0, null, undefined or "") and gives back false. Similarly anything that is truthy (like 14, "hello", [4], {a:1}) and give back true. !! works because the first exclamation mark gives the 'not' of the expression which is always true or false, then the second exclamation mark gives the opposite of that (false or true).
Getting back to the challenge, it wants to apply the not-operator 'a' times and compare to the 'b' value. So something like this would work:
function notNotNot(a, b) { return !!(a%2 - b); }
console.log("notNotNot(1, true)",notNotNot(1, true));
console.log("notNotNot(2, false)",notNotNot(2, false));
console.log("notNotNot(6, true)",notNotNot(6, true));
Bitwise operators always convert their operands to an integer. So, 4 >> true is the same as 4 >> 1 which will do a bit shift right by one position
(decimal) 4 = (binary) 100
(binary) 100 >> 1 = (binary) 010
(binary) 010 = (decimal) 2
console.log(4 >> true);
So, using true or false is a just a roundabout way to use 1 or 0.
The notNotNot function has very simple operation, overall:
a%2 converts the first number into 0 for even or 1 for odd.
>> b shifts right by either 0 positions for false or 1 position for true.
a is odd (1) and b is false = 1
there is zero shifts to the right, so the number remains the same.
a is odd (1) and b is true = 0
the only set bit 1 is shifted right and discarded.
a is even (0) and b is false = 0
there is zero shifts to the right, so the number remains the same.
a is even (0) and b is true = 0
the base number is 0 which doesn't have any bits set, so shifting right any amount does not change it.
!!() converts the result to boolean.
With that said, the solution here is wrong, since notNotNot(2, true) will produce false - a is even and b is true. The expectation is that it will produce true since !!true = true. The same problem is present for any even number and true.
It can be easily fixed by using bitwise XOR instead of right shift:
a is odd (1) and b is false = 1
both match, so they are flipped to 0
a is odd (1) and b is true = 0
they don't match, so we get 1
a is even (0) and b is false = 0
both match, so we get 0
a is even (0) and b is true = 1
they don't match, so we get 1
notNotNot = (a,b) => !!(a%2 ^ b);
console.log("!!true = ", notNotNot(2, true))
console.log("!!!true =", notNotNot(3, true))
console.log("!!false = ", notNotNot(2, false))
console.log("!!!false = ", notNotNot(3, false))
//bonus
console.log("true = ", notNotNot(0, true))
console.log("false = ", notNotNot(0, false))
Just for completeness sake, in case you want a fully bitwise operation:
The modulo operation %2 can be changed to a bitwise AND &1 get the lowest bit. For even numbers, this would yield 0 since you'd be computing
xxx0
&
0001
which is zero. And for odd numbers the same applies but you'd get one as a result:
xxx1
&
0001
So the results of a&1 and a%2 are identical. Furthermore, even though bitwise operations convert the number to a 32-bit signed integer that doesn't matter as the parity would be preserved.
//larger than 31 bits
const largeValue = 2**31 + 1;
//larger than 32 bits
const veryLargeValue = 2**32 + 1
console.log("2**31 + 1 =", largeValue);
console.log("2**32 + 1 =", veryLargeValue);
console.log("2**31 + 1 to 32-bit signed integer =", largeValue | 0);
console.log("2**32 + 1 to 32-bit signed integer = ", veryLargeValue | 0);
const isOddModulo = number =>
console.log(`(${number} % 2) can detect an odd number: ${(number % 2) === 1}`);
const isOddBitwise = number =>
console.log(`(${number} & 1) can detect an odd number: ${(number & 1) === 1}`);
isOddModulo(largeValue);
isOddBitwise(largeValue);
isOddModulo(veryLargeValue);
isOddBitwise(veryLargeValue);
Firstly, (a,b) => !!(a%2 >> b) does not match the results of the examples. I will break down exactly what it's doing using notNotNot(6, true) ➞ true.
Fist a%2, simply get a divide by 2 return the remainder. So we will get 0 for an even number and 1 for an odd number. a = 6 a%2 = 0 in this case.
Then 0 >> b shift 1 number off from the right because as you said true evaluates to 1. So we get 0 >> 1 = 0.
Last !!(0), is simple, and can be broken down like so, !0 = true, then !true = false.
So if we think about this as long as b is true, we will always get returned false. Let's say we have a = 5, b = true evaluating to 5%2 = 1, 1 >> 1 = 0. You can see because of the mod (%2) we will only ever have 1 or 0 (only ever have 1 digit) and true will always shift off the 1 when we have it.
A simple way to look at this problem is like an isEvenOrNot function. So a is the number we are checking and b is a boolean to check if it's even (true) or not even (false). This works because every second not added will be true.
So a solution using bitwise could be something like: (a,b) => !!(a&1 ^ b).
I will let you have the fun of breaking down why it works! :)
A little bit more into explaining how shift works with a boolean. So true as you said will be 1 and false will be 0. So as shown in your example, 0101 >> true is the same as 0101 >> 1.
I hope this helps.
I used the following as a reference for bitwise: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators
(a%2) //ignore all but the least significant bit (LSB)
(a%2 >> b ) //if TRUE, shifts right, resolves to 0
//if FALSE, no shift, resolves to LSB
// 0 and LSB are both integers so convert to boolean by using logical/boolean NOT
!(a%2 >> b ) //resolves to the boolean which it is NOT
!!(a%2 >> b ) //resolves to the boolean which it is NOT NOT
NB For either boolean,
an even number of NOTs results in the original boolean
an odd number of NOTs results in the opposite boolean
The LSB of any number dictates whether the number is odd or even.(0 even, 1 odd)
I see that your task is:
/* Create a function where given n number of "not",
evaluate whether it's true or false.*/
I don't know why you are writing notnotnot function
for me that is not what the task asks.
So according to the task I made that function not
that accepts a number of "nots" and evaluates them.
The first way
function not(n) {
return Boolean(n - n - 1);
}
The second way using XOr(^)
function not(n) {
return Boolean(bool ^ (bool - 1));
}
The third way using Mod(%) pointed by #VLAZ
function not(n) {
return Boolean(n % 2);
}
The fourth way using bitwise And(&)
function not(n) {
return Boolean(n & 1);
}
Test
not(0)
//> false
not(1)
//> true
not(2)
//> false
not(515)
//> true
Lets analysis solution first
notNotNot(oddNumber, true) ➞ false
notNotNot(evenNumber, true) ➞ true
notNotNot(oddNumber, false) ➞ true
notNotNot(evenNumber, false) ➞ false
Now analysis the for (a,b) => !!(a%2 >> b)
a%2 == 0 ➞ even number
a%2 == 1 ➞ odd number
// For a%2 == 0
a%2 >> b ➞ if b is true ➞ 0 >> 1 ➞ 0 // Not working
a%2 >> b ➞ if b is false ➞ 0 >> 0 ➞ 0
// For a%2 == 1
a%2 >> b ➞ if b is true ➞ 1 >> 1 ➞ 0
a%2 >> b ➞ if b is false ➞ 1 >> 0 ➞ 1
Thats means this is not working for notNotNot(6, true) is true but current solution gives false.
We can you ^(XOR) operator to make it correct Like (a,b) => !!(a%2 ^ b)
Now analysis the for (a,b) => !!(a%2 ^ b)
a%2 == 0 ➞ even number
a%2 == 1 ➞ odd number
// For a%2 == 0
a%2 ^ b ➞ if b is true ➞ 0 ^ 1 ➞ 1 // Now working
a%2 ^ b ➞ if b is false ➞ 0 ^ 0 ➞ 0
// For a%2 == 1
a%2 ^ b ➞ if b is true ➞ 1 ^ 1 ➞ 0
a%2 ^ b ➞ if b is false ➞ 1 ^ 0 ➞ 1
!(a%2 ^ b) use `!` to make int as boolean but solution result will reversed then
!!(a%2 ^ b) use `!` again to reversed it again and make it correct.
Example:
notNotNot = (a,b) => !!(a%2 ^ b);
console.log("!!!!true = ", notNotNot(4, true))
console.log("!!!!false = ", notNotNot(4, false))
console.log("!!!true =", notNotNot(3, true))
console.log("!!!false = ", notNotNot(3, false))

What does the "^=" operator do in this find non-paired number algorithm? [duplicate]

This question already has answers here:
find the only unpaired element in the array
(10 answers)
What are bitwise operators?
(9 answers)
What do these JavaScript bitwise operators do?
(3 answers)
Closed 5 years ago.
Saw an interesting piece of code to find a lonely number in a list of duplicate numbers (where every number in the list occurs twice except for one).
function findNonPaired(listOfNumbers) {
let nonPairedNumber = 0
listOfNumbers.forEach((n) => {
nonPairedNumber ^= n
})
return nonPairedNumber
}
const x = [1,5,4,3,9,2,3,1,4,5,9]
console.log(findNonPaired(x))
This solution looks very elegant, but I'm curious at to what the ^= operator is actually doing here?
a ^= b is the same as a = a ^ b where ^ is the bitwise XOR operator.
0 ^ 0 === 0
1 ^ 0 === 1
0 ^ 1 === 1
1 ^ 1 === 0
This is a neat algorithm. Let's trace one execution with the list [8, 12, 8] for example:
0 ^ 8 = 0000 ^ 1000 = 1000
1000 ^ 1100 = 0100
0100 ^ 1000 = 1100 = 12
The word "duplicate" isn't correct. This algorithm tests for parity. A simple but somewhat wrong definition is "when everything has a pair". pair...parity.
[2,2,2,3,3,5,5,5,5] will return 2 because everything else has a pair.
[3,4,5] will actually return 2 (011^100^101 -> 010) because that is the xor of all the unpaired items.
Like other answers say - it is a bitwise XOR.
About the algorythm - it is cool if you are sure that the duplicates are even count. When a number is XOR-ed with x and later again XOR-ed with x it will return to it's previuos value. If one number is seen 3 times in this chain, the 3-rd occurence will fool this algorythm.
Also if there is one more value that is single in the chain, like:
a, b, c, X, a, c, b, Y
the result will be (X ^ Y) and you can't be sure if you have one unique value or more.

Can I represent large integers in Node 6 for only exponentiation without a dependency?

I am working on a kata that asks for the last digit of a[0] ^ (a[1] ^ (a[2] ^ ... (a[n-1] ^ a[n]))). When computing the answer, eventually Math.pow exceeds Number.MAX_SAFE_INTEGER, causing modexp below to return erroneous results.
#user2357112 says that JS needs a library for arbitrary-precision integers, which is all well and good, but nothing in the kata indicates that such a library is available in the remote environment, or even that I need one.
Since the kata and SO point in different directions on this matter, I want to learn if I can feasibly represent big integers ONLY for the purposes of solving this kata without writing an entire library.
My in-progress code is below, and it passes many tests before printing incorrect results. Some code was omitted to avoid spoilers.
TL;DR: If I cannot use a library, what can I do to feasibly represent large integers for the use case indicated by Math.pow()?
function modexp(b, e) {
let c = 1
while(e) {
if (e & 1)
c = c * b % 10
e >>= 1
b = b * b % 10
}
return c;
}
function lastDigit(as) {
if (!as || !as.length) return 1;
let e = as.slice(1).reverse().reduce((p,c) => Math.pow(c,p));
return modexp(as[0], Number(e));
}
This is obviously an X-Y problem. You don't need large integers.
You need to go back to elementary school math.
What's multiplication? Well let's take one example:
WARNING: SPOILERS! Don't read the following if you want to figure it out yourself!
1 2
x 2 3
------
3 6 last digit 6
2 4
------
2 7 6 notice how last digit is only involved
in ONE multiplication operation?
Hmm.. there seems to be a pattern. Let's see if that pattern holds. Let's multiply 12 x 23 x 23 by only doing the last digit:
1 2
x 2 3
------
6 calculate ONLY last digit
x 2 3
------
8 answer is: last digit is 8
Let's check our answer:
1 2
x 2 3
------
3 6
2 4
------
2 7 6
x 2 3
------
8 2 8
5 5 2
-------
6 3 4 8 last digit is INDEED 8
So it seems that you can find the last digit by only calculating the last digit. Let's try to implement a powLastDigit() function.
WARNING: SPOILERS! DON'T READ THE CODE IF YOU WANT TO WRITE IT YOURSELF!
function powLastDigit (number,power) {
var x = number;
for (var y=1; y<power; y++) {
x = ((x%10)*(number%10))%10; // we only care about last digit!
}
return x;
}
Let's check if we are right:
> powLastDigit(3,7)
7
> Math.pow(3,7)
2187
> powLastDigit(5,8)
5
> Math.pow(5,8)
390625
> powLastDigit(7,12)
1
> Math.pow(7,12)
13841287201
OK. Looks like it's working. Now you can use this function to solve your problem. It has no issues with very large exponents because it doesn't deal with large numbers:
> powLastDigit(2323,123456789)
3
Optimization
The above code is slow because it uses a loop. It's possible to speed it up by using Math.pow() instead. I'll leave that as a homework problem.
I use bit array to represent a positive integer;
[0,0,1,1] // bit array of 12 (MSB=rightmost)
This structure is used to manipulate the overall exponent, E
a[1] ^ (a[2] .. (a[n-1] ^ a[n])) // E
(!)There is a relation between LSD(a[0]) and the overall exponent E as below
//LSD(a[0]) LSD(LSD(a[0]) ^ E) for
// [E/4R0, E/4R1, E/4R2, E/4R3]
//--------- ----------------------------
// 0 [0, 0, 0, 0]
// 1 [1, 1, 1, 1]
// 2 [6, 2, 4, 8]
// 3 [1, 3, 9, 7]
// 4 [6, 4, 6, 4]
// 5 [5, 5, 5, 5]
// 6 [6, 6, 6, 6]
// 7 [1, 7, 9, 3]
// 8 [6, 8, 4, 2]
// 9 [1, 9, 1, 9]
For example, find least significant digit of (2 ^ (2 ^ 3)),
// LSD(a[0]) is 2
// E is 8
// implies E mod 4 is 0
// LSD(LSD(a[0]) ^ E)
// for E/4R0 is 6 (ans)
To determine E mod 4,
E[0] + E[1] * 2 // the two LSBs
To summarize, I create a data structure, bit array, to store large integers,
mainly for the intermediate value of exponent-part. The bit array is dynamic length obtaining max. 9007199254740991 bits, if all bits are set, the value in decimal is 2 ^ (9007199254740991 + 1) - 1. This bit array will never be converted back to decimal(safe). The only interesting information of overall exponent, E, is its two least significant bits, they are the remainder of E/4
which can be applied to the above relation(!).
Obviously, Math.pow will not work for bit array, so I handcraft a simple exp() for it. This is trivial since the fact that
//exponentiation == lots of multiplications == lots of additions
//it is not difficult to implement addition on bit array
This is the fiddle demonstrating above idea ONLY. It is intended to be slow if the E is really large. FYI
LSD.find([3,4,5,6]) // my Nightly hanged ~3s to find lsd
You may optimize the Bits.exp by means of childprocesses, web workers, debounce function, simd etc. Good luck.
You don't really need a bigint library to solve this kata.
You are only interested in the last digit of the result, and fortunately there is a property of powers that helps us with this. We effectively want to compute a power in modulus 10. Yes, modular exponentiation does help us a bit here, but the problem is that the exponent is very large as well - too large to compute, and too large to run a loop with that many iterations. But we don't need to, all we are interested in is the modulus of the result.
And there is a pattern! Let's take 4x as an example:
x 4^x (4^x)%10
--------------------------
0 4^0 = 1 1
1 4^1 = 4 4
2 4^2 = 16 6
3 4^3 = 64 4
4 4^4 = 256 6
5 4^5 = 1024 4
… …
20 4^20 = ??? 6 sic!
21 4^21 = ??? 4
… …
You will be able to find these patterns for all numbers in all modular bases. They all share the same characteristic: there's a threshold below which the remainder is irregular, and then they form a repeating sequence. To get a number in this sequence, we only need to perform a modulo operation on the exponent!
For the example above ((4^x)%10), we use a lookup table 0 → 6, 1 → 4 and compute x % 2; the threshold is 1. In JavaScript code, it might look like this:
x < 1 ? 1 : [6, 4][x % 2];
Of course, x is a very large number formed by the repeated exponentiation of the rest of the input, but we do not need to compute it as whole - we only want to know
whether it is smaller than a relatively small number (trivial)
what the remainder after division by q is - just a recursive call to the function we're implementing!

Decomposing a value into results of powers of two

Is it possible to get the integers that, being results of powers of two, forms a value?
Example:
129 resolves [1, 128]
77 resolves [1, 4, 8, 64]
I already thought about using Math.log and doing also a foreach with a bitwise comparator. Is any other more beautiful solution?
The easiest way is to use a single bit value, starting with 1 and shift that bit 'left' until its value is greater than the value to check, comparing each bit step bitwise with the value. The bits that are set can be stored in an array.
function GetBits(value) {
var b = 1;
var res = [];
while (b <= value) {
if (b & value) res.push(b);
b <<= 1;
}
return res;
}
console.log(GetBits(129));
console.log(GetBits(77));
console.log(GetBits(255));
Since shifting the bit can be seen as a power of 2, you can push the current bit value directly into the result array.
Example
You can adapt solutions from other languages to javascript. In this SO question you'll find some ways of solving the problem using Java (you can choose the one you find more elegant).
decomposing a value into powers of two
I adapted one of those answers to javascript and come up with this code:
var powers = [], power = 0, n = 129;// Gives [1,128] as output.
while (n != 0) {
if ((n & 1) != 0) {
powers.push(1 << power);
}
++power;
n >>>= 1;
}
console.log(powers);
Fiddle
Find the largest power of two contained in the number.
Subtract from the original number and Add it to list.
Decrement the exponent and check if new 2's power is less than the number.
If less then subtract it from the original number and add it to list.
Otherwise go to step 3.
Exit when your number comes to 0.
I am thinking of creating a list of all power of 2 numbers <= your number, then use an addition- subtraction algorithm to find out the group of correct numbers.
For example number 77:
the group of factors is { 1,2,4,8,16,32,64} [ 64 is the greatest power of 2 less than or equal 77]
An algorithm that continuously subtract the greatest number less than or equal to your number from the group you just created, until you get zero.
77-64 = 13 ==> [64]
13-8 = 7 ==> [8]
7-4 = 3 ==> [4]
3-2 = 1 ==> [2]
1-1 = 0 ==> [1]
Hope you understand my algorithm, pardo my bad english.
function getBits(val, factor) {
factor = factor || 1;
if(val) {
return (val % 2 ? [factor] : []).concat(getBits(val>>1, factor*2))
}
return [];
}
alert(getBits(77));

How do I swap endian-ness (byte order) of a variable in javascript

I am receiving and sending a decimal representation of two little endian numbers. I would like to:
shift one variable 8 bits left
OR them
shift a variable number of bits
create 2 8 bit numbers representing the first and second half of the 16 bit number.
javascript (according to https://developer.mozilla.org/en/JavaScript/Reference/Operators/Bitwise_Operators) uses big endian representation when shifting...
endianness is a bit foreign to me (I am only 90 percent sure that my outlined steps are what i want.) so swapping is a bit dizzying. please help! I only really need to know how to swap the order in an efficient manner. (I can only think of using a for loop on a toString() return value)
function swap16(val) {
return ((val & 0xFF) << 8)
| ((val >> 8) & 0xFF);
}
Explanation:
Let's say that val is, for example, 0xAABB.
Mask val to get the LSB by &ing with 0xFF: result is 0xBB.
Shift that result 8 bits to the left: result is 0xBB00.
Shift val 8 bits to the right: result is 0xAA (the LSB has "dropped off" the right-hand side).
Mask that result to get the LSB by &ing with 0xFF: result is 0xAA.
Combine the results from steps 3 and step 5 by |ing them together:
0xBB00 | 0xAA is 0xBBAA.
function swap32(val) {
return ((val & 0xFF) << 24)
| ((val & 0xFF00) << 8)
| ((val >> 8) & 0xFF00)
| ((val >> 24) & 0xFF);
}
Explanation:
Let's say that val is, for example, 0xAABBCCDD.
Mask val to get the LSB by &ing with 0xFF: result is 0xDD.
Shift that result 24 bits to the left: result is 0xDD000000.
Mask val to get the second byte by &ing with 0xFF00: result is 0xCC00.
Shift that result 8 bits to the left: result is 0xCC0000.
Shift val 8 bits to the right: result is 0xAABBCC (the LSB has "dropped off" the right-hand side).
Mask that result to get the second byte by &ing with 0xFF00: result is 0xBB00.
Shift val 24 bits to the right: result is 0xAA (everything except the MSB has "dropped off" the right-hand side).
Mask that result to get the LSB by &ing with 0xFF: result is 0xAA.
Combine the results from steps 3, 5, 7 and 9 by |ing them together:
0xDD000000 | 0xCC0000 | 0xBB00 | 0xAA is 0xDDCCBBAA.
Such function can be used to change endianness in js:
const changeEndianness = (string) => {
const result = [];
let len = string.length - 2;
while (len >= 0) {
result.push(string.substr(len, 2));
len -= 2;
}
return result.join('');
}
changeEndianness('AA00FF1234'); /// '3412FF00AA'
Use the << (bit shift) operator. Ex: 1 << 2 == 4.
I really think that the underlying implementation of JavaScript will use whatever endianess the platform it is running on is using. Since you cannot directly access memory in JavaScript you won't ever have to worry about how numbers are represented physically in memory. Bit shifting integer values always yield the same result no matter the endianess. You only see a difference when looking at individual bytes in memory using pointers.
Here is a oneliner for arrays to swap between big and little endian (and vise versa). The swapping is done using reverse on byte level. I guess for large arrays, it is more efficient than looping over scalar swap function.
function swapbyte(x) {
return new Float64Array(new Int8Array(x.buffer).reverse().buffer).reverse()
}
// Example
buf = new ArrayBuffer(16); // for 2 float64 numbers
enBig = new Float64Array(buf);
enBig[0] = 3.2073756306779606e-192;
enBig[1] = 2.7604354232023903e+199;
enLittle = swapbyte(enBig)
// two famous numbers are revealed
console.log(enLittle)
// Float64Array [ 6.283185307179586, 2.718281828459045 ]
// swapping again yields the original input
console.log(swapbyte(enLittle))
// Float64Array [ 3.2073756306779606e-192, 2.7604354232023903e+199 ]

Categories