1

'Write a function named sumDigits which takes a number as input and returns the sum of each of the number's decimal digits.'

How can I sum the digits with the first digit being negative?

For example: sumDigits(-32); // -3 + 2 = -1;

I was able to solve it partially.

function sumDigits(number) {
  return Math.abs(number).toString().split("").reduce(function(a, b) {
    return parseInt(a) + parseInt(b);
  }, 0);
}

console.log( sumDigits(-32) );
benvc
  • 14,448
  • 4
  • 33
  • 54
pasha
  • 51
  • 6
  • 5
    "for exmple: sumDigits(-32); // -3 + 2 = -1;" - This contradicts your instructions. The sum of the **absolute value** of each of the number's decimal digits would be `|-3| + 2 = 5`, no? – Tyler Roper Apr 16 '19 at 19:55
  • 1
    theres no negative absolute values. – Daniel A. White Apr 16 '19 at 19:55
  • 2
    I guess your teacher doesn't want you to use string functions for this. Besides, "an absolute value of a digit" is nonsense. – georg Apr 16 '19 at 20:00
  • btw, `Math.abs(number)` removes the sign. – Nina Scholz Apr 16 '19 at 20:15
  • "decimal digits" means only the digits right of the decimal point. – Ronnie Royston Apr 16 '19 at 20:36
  • @RonRoyston - decimal digits is an imprecise term at best. A quick search produces definitions that equate to simply numerical digits as well as definitions that equate to digits to the right of the decimal point. OP should probably clarify the meaning of that phrasing. – benvc Apr 16 '19 at 20:41
  • my google says "The decimal point separates the whole number on the left from the _decimal digits_ on the right." – Ronnie Royston Apr 16 '19 at 20:43

7 Answers7

3

Simple math and recursion make short work of this problem.

Recall that when you divide a number by 10, the remainder is its rightmost decimal digit and the integer part of the quotient is the number formed by the remaining digits. In other words:

let n = 5678;
console.log(n % 10); // => 8
console.log(Math.floor(n / 10)); // => 567

With this in mind, summing a number's digits is a straightforward recursive procedure:

Procedure(n)

  1. Divide n by 10.
    • Set digit to the remainder.
    • Set n to the integer part of the quotient.
  2. If n = 0, return digit.
  3. Otherwise, return digit + Procedure(n)

Keeping the sign for the leftmost digit adds a small amount of complexity, but not much. Here's how it looks in JavaScript:

function digitSum(n, sign=1) {
  if (n < 0) {
    sign = -1; // Save the sign
    n = Math.abs(n);
  }

  const digit = n % 10; // Remainder of |n÷10|
  n = Math.floor(n / 10); // Integer part of |n÷10|

  if (n === 0) {
    return sign * digit; // No digits left, return final digit with sign
  }
  return digit + digitSum(n, sign); // Add digit to sum of remaining digits
}

console.log(digitSum(32)); // => 5
console.log(digitSum(-32)); // => -1
Jordan Running
  • 102,619
  • 17
  • 182
  • 182
  • 2
    Good stuff, however `parseInt(n / 10)` looks quite roundabout (you're basically converting it to string and then back to number). How about `Math.floor(n/10)` or `(n/10)|0`? – georg Apr 17 '19 at 08:59
  • @georg You're right. I used `parseInt` because `Math.floor` rounds negative numbers down (`Math.floor(-1.5) === -2`) and for some reason I was certain `parseInt` wouldn't bother coercing a numeric argument to a string, but [looking at the spec](https://www.ecma-international.org/ecma-262/6.0/#sec-parseint-string-radix) I see that I was mistaken. `|0` would have been a better solution but it's moot now since I do `Math.abs` first so `Math.floor` works fine. I've updated my answer. Thanks for the feedback! – Jordan Running Apr 17 '19 at 16:18
1

Here is a way to do it with Array.prototype.reduce().

  1. Stringify the input and split it on each character.
  2. Iterate over the characters with reduce.
    1. Initialize the accumulator with a sum of 0 and a multiplier of 1.
    2. If the first character is a -, set the multiplier to -1
    3. For the subsequent characters, multiply the digit with the multiplier and add it to the sum. Then set the multiplier back to 1 so the next digits will only be multiplied by 1.

const sumDigits = x => [...`${x}`].reduce(({ sum, mult }, x, i) => {
  return i === 0 && x === '-' ? { sum: 0, mult: -1 } : { sum: sum + mult * x, mult: 1 };
}, { sum: 0, mult: 1 }).sum;

console.log(sumDigits(-32));  // -1
console.log(sumDigits(32));   //  5
console.log(sumDigits(5555)); //  20
jo_va
  • 13,504
  • 3
  • 23
  • 47
1

Here's a way you can do it without String conversion -

const sumDigits = (n = 0) =>
  n < 0
    ? n > -10
      ? n
      : (-n % 10) + sumDigits (n / 10 >> 0)
    : n < 10
      ? n
      : (n % 10) + sumDigits (n / 10 >> 0)
      
      
console.log(sumDigits(-321))
// (-3 + 2 + 1)
// => 0

console.log(sumDigits(321))
// (3 + 2 + 1)
// => 6   

The same answer using imperative style -

const sumDigits = (n = 0) =>
{ if (n < 0)
    if (n > -10)
      return n
    else
      return (-n % 10) + sumDigits (n / 10 >> 0)
  else
    if (n < 10)
      return n
    else
      return (n % 10) + sumDigits (n / 10 >> 0)
}     
      
console.log(sumDigits(-321))
// (-3 + 2 + 1)
// => 0

console.log(sumDigits(321))
// (3 + 2 + 1)
// => 6   
Mulan
  • 129,518
  • 31
  • 228
  • 259
1

An approach that does not require converting to a string adapted from another answer by @NinaScholz to a closely related question (for those that are bitwise shift operator challenged).

Converts the number to its absolute value, loops with modulus operator to sum the remainder after dividing by 10 until a ones value remains, and then subtracts the leftmost digit if the original number was negative.

const sumDigits = (n) => {
  const negative = !!(n < 0);
  let sum = 0;
  let num = negative ? Math.abs(n) : n;
  while (num) {
    if (negative && num <= 10) {
      sum -= num % 10;
    } else {
      sum += num % 10;
    }
    
    num = Math.floor(num / 10);
  }
  
  return sum;
};

console.log(sumDigits(-32));
// -1
benvc
  • 14,448
  • 4
  • 33
  • 54
0

You could take a different method for separating the digits and keep the first one with a possible sign.

'-32'.match(/-?\d/g)

returns

['-3', '2']

function sumDigits(number) {
    return number.toString().match(/-?\d/g).reduce(function(a, b) {
        return a + +b;
    }, 0);
}

console.log(sumDigits(-32));
Community
  • 1
  • 1
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

First, "decimal digits" means only the characters to the right of the decimal point. Converting the number to a string sets you up as JavaScript strings are arrays of characters. So, then it's just a matter of splitting out the decimal digits then summing them by iterating that array, then converting back to a number type.

//'Write a function named sumDigits which takes a number as input and returns the sum of each of the number's decimal digits.'

var a = 10.12345;
var b = -1012345;

function sumDigits(x){
  var result = 0;
  x = x.toString();
  x = x.split('.')[1];
  if (x == null){
    //there's not decimal digits to sum!
    return "there's not decimal digits to sum!"
  }
  for (var i = 0; i < x.length; i++) {
    if (digit >= 0 && digit <= 9) { //just in case, probably unnecessary
      var digit = Number(x[i]);
      result = result + digit;
    }
  }
  //if you care about negative uncomment this
  //if(x[0] === "-"){
  //  result = result * -1;
  //}
  return result;
}

console.log(sumDigits(a));
console.log(sumDigits(b));
Ronnie Royston
  • 16,778
  • 6
  • 77
  • 91
0

// try this to get the sum of negatives:

const sumOfNegative = (numbers) => {
  let sum = 0;
  numbers.forEach((number) => {
    if (number < 0) {
      sum += number;
    }
  });
  return sum;
};