371. Sum of Two Integers

Description

Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -.

Example:
Given a = 1 and b = 2, return 3.

Solution

Solution 1

/**
 * JavaScript bitwise operators are converted to signed 32-bit integers
 * thus the accuracy of the range here is from -2147483648 ~ 2147483647
 * @param {number} num1
 * @param {number} num2
 * @return {number}
 */
var getSum = function(num1, num2) {
    "use strict";
    let result = [], carry = 0;
    for (; num1 || num2; num1=num1>>>1, num2=num2>>>1) {
        result.push((num1 ^ num2 ^ carry) & 1);
        // If there are more than two 1s than set carry as 1 for the next round of addition
        if ((num1 & num2 & 1) || (num1 & carry & 1) || (num2 & carry & 1)) {
            carry = 1;
        } else {
            carry = 0;
        }
    }
    if (carry) {
        result.push(1);
    }
    return ~~parseInt(result.reverse().join(""), 2);
};

Solution 2

/**
 * Use string in two's complement calculation to bypass the bitwise limit in JavaScript
 * JavaScript Numbers are 64-bit floating point values
 * the largest exact integral value is 2^53-1
 * thus the accuracy of the range here is from -9007199254740991 ~ 9007199254740991
 * @param {number} num1
 * @param {number} num2
 * @return {number}
 */
var getSum = function(num1, num2) {
    "use strict";
    /** 
     * Calculate the sum of two binaries
     * @param {string} a: The binary to be added
     * @param {string} b: The binary to be added
     * @return {string} The resulting binary
     */
    function binAdder(a, b) {
        a = a.split("").reverse();
        b = b.split("").reverse();
        let binSum = [], carry = 0;
        let maxLength = a.length > b.length ? a.length : b.length;
        for (let i = 0; i < maxLength; i++) {
            binSum.push((a[i] ^ b[i] ^ carry) & 1);
            // If there are more than two 1s than set carry as 1 for the next round of addition
            if ((a[i] & b[i] & 1) || (a[i] & carry & 1) || (b[i] & carry & 1)) {
                carry = 1;
            } else {
                carry = 0;
            }
        }
        if (carry) {
            binSum.push("1");
        }
        return binSum.reverse().join("");
    }
    /** 
     * Padding string with specific character
     * @param {string} str: The string to be padded
     * @param {number} offset: how many characters needed to pad
     * @param {string} pos: The padding position (can either be "left" or "right")
     * @param {string} char: The character to pad
     * @return {string} The resulting string
     */
    function padding(str, offset, pos, char) {
        let padding = "";
        while (offset) {
            padding = padding + char;
            offset--;
        }
        if (pos === "left") {
            return (padding + str);
        }
        return (str + padding)
    }
    /** 
     * Calculate the sum of two binaries
     * one is positive, the other is negative represented as 2's complement
     * @param {string} a: The binary to be added
     * @param {string} b: The binary to be added
     * @param {number} pos: The position of negative addend (1: a, 2: b)
     * @return {string} The resulting binary
     */
    function binAdder2sComp(a, b, pos) {
        let offset = 0;
        if (pos === 1) {
            offset = b.length - a.length;
            if (offset > 0) {
                return binAdder(padding(a, offset, "left", "1"), b);
            }
        } else {
            offset = a.length - b.length;
            if (offset > 0) {
                return binAdder(a, padding(b, offset, "left", "1"));
            }
        }
        return binAdder(a, b);
    }
    /** 
     * Calculate 2's complement of a binary
     * @param {string} a: The binary to be calculated
     * @return {string} The 2's complement of input binary
     */
    function twosComplement(a) {
        a = a.split("");
        for (let i = 0; i < a.length; i++) {
            if (a[i] === "1") {
                a[i] = "0";
            } else {
                a[i] = "1";
            }
        }
        return binAdder(a.join(""), "1");
    }
    /** 
     * Handle the overflow after the summation of 2's complement binaries
     * @param {string} addend1: The addend of summation
     * @param {string} addend2: The addend of summation
     * @param {string} sum: The result of summation
     * @return {number} Resulting decimal number
     */
    function handleOverflow(addend1, addend2, sum) {
        let maxlength = addend1.length > addend2.length ? addend1.length : addend2.length;
        // Drop carry 
        if (sum.length > maxlength) {
            return parseInt(sum.slice(1), 2);
        } else {
            return -parseInt(twosComplement(sum), 2);
        }
    }
    /* Main */
    num1 = parseInt(num1, 10); num2 = parseInt(num2, 10);
    if (num1 >= 0 && num2 >= 0) {
        return parseInt(binAdder(num1.toString(2), num2.toString(2)), 2);
    } else if (num1 < 0 && num2 < 0) {
        num1 = -num1;
        num2 = -num2;
        return -parseInt(binAdder(num1.toString(2), num2.toString(2)), 2);
    } else {
        if (num1 < 0) {
            num1 = -num1;
            let tmpSum = binAdder2sComp(twosComplement(num1.toString(2)), num2.toString(2), 1);
            return handleOverflow(num1.toString(2), num2.toString(2), tmpSum);
        }
        if (num2 < 0) {
            num2 = -num2;
            let tmpSum = binAdder2sComp(num1.toString(2), twosComplement(num2.toString(2)), 2);
            return handleOverflow(num1.toString(2), num2.toString(2), tmpSum);
        }
    }
};

results matching ""

    No results matching ""