Perform multiplication of any two integers positive or negative through bit manipulations (#201)

This commit is contained in:
ADITYA 2018-09-08 15:51:03 -04:00 committed by Oleksii Trekhleb
parent 1a62078f26
commit bc8943dee2
5 changed files with 109 additions and 14 deletions

View File

@ -35,6 +35,20 @@ This method is a combination of "Clear Bit" and "Set Bit" methods.
> See [updateBit.js](updateBit.js) for further details.
#### isEven
This method determines if the number provided is even.
```
Number: 5
isEven: false
Number: 4
isEven: true
```
> See [isEven.js](isEven.js) for further details.
#### Multiply By Two
This method shifts original number by one bit to the left.
@ -91,7 +105,25 @@ inverting all of the bits of the number and adding 1 to it.
> See [switchSign.js](switchSign.js) for further details.
#### Multiply Two Numbers
#### Multiply Two Signed Numbers
This method multiplies two signed integer numbers using bitwise operators.
This method is based on the following :
```text
a * b can be written in the below formats
0 if a is zero or b is zero or both a and b are zeroes
2a * (b/2) if b is even
2a * (b - 1)/2 + a if b is odd and positive
2a * (b + 1)/2 - a if b is odd and negative
```
The advantage of this approach is that in each recursive step one of the operands reduces to half its original value.
Hence, the run time complexity is O(log b) where b is the operand that reduces to half on each recursive step.
> See [multiply.js](multiply.js) for further details.
#### Multiply Two Unsigned Numbers
This method multiplies two integer numbers using bitwise operators.
This method is based on that "Every number can be denoted as the sum of powers of 2".

View File

@ -0,0 +1,11 @@
import isEven from '../isEven';
describe('isEven', () => {
it('should detect if a number is even', () => {
expect(isEven(0)).toBe(true);
expect(isEven(2)).toBe(true);
expect(isEven(-2)).toBe(true);
expect(isEven(1)).toBe(false);
expect(isEven(-1)).toBe(false);
});
});

View File

@ -0,0 +1,16 @@
import multiply from '../multiply';
describe('multiply', () => {
it('should multiply two numbers', () => {
expect(multiply(0, 0)).toBe(0);
expect(multiply(2, 0)).toBe(0);
expect(multiply(0, 2)).toBe(0);
expect(multiply(1, 2)).toBe(2);
expect(multiply(2, 1)).toBe(2);
expect(multiply(6, 6)).toBe(36);
expect(multiply(-2, 4)).toBe(-8);
expect(multiply(4, -2)).toBe(-8);
expect(multiply(-4, -4)).toBe(16);
expect(multiply(4, -5)).toBe(-20);
});
});

View File

@ -0,0 +1,7 @@
/**
* @param {number} number
* @return bool
*/
export default function isEven(number) {
return (number & 1) === 0;
}

View File

@ -0,0 +1,29 @@
import divideByTwo from './divideByTwo';
import isEven from './isEven';
import multiplyByTwo from './multiplyByTwo';
/**
* FUNCTION DEFINITION
* multiply(a, b) = 0 if a is zero or b is zero or if both a and b are zeros
* multiply(a, b) = multiply(2a, b/2) if b is even
* multiply(a, b) = multiply(2a, (b-1)/2) + a if b is odd and b is positive
* multiply(a, b) = multiply(2a, (b+1)/2) - a if b is odd and b is negative
*
* COMPLEXITY
* O(log b)
* @param {number} a
* @param {number} b
* @return {number} a * b
*/
export default function multiply(a, b) {
if (b === 0 || a === 0) {
return 0;
}
const multiplyByOddPositive = () => multiply(multiplyByTwo(a), divideByTwo(b - 1)) + a;
const multiplyByOddNegative = () => multiply(multiplyByTwo(a), divideByTwo(b + 1)) - a;
const multiplyByEven = () => multiply(multiplyByTwo(a), divideByTwo(b));
const multiplyByOdd = () => (b > 0 ? multiplyByOddPositive() : multiplyByOddNegative());
return isEven(b) ? multiplyByEven() : multiplyByOdd();
}