40

I need to separate an integer into two numbers. Something like dividing by two but I only want integer components as a result, such as:

6 = 3 and 3
7 = 4 and 3

I tried the following, but I'm not sure its the best solution.

var number = 7;
var part1 = 0;
var part2 = 0;

if((number % 2) == 0) {
    part1 = number / 2;
    part2 = number / 2;
}
else {
    part1 = parseInt((number / 2) + 1);
    part2 = parseInt(number / 2);
}

This does what I want, but I don't think this code is clean.

Are there better ways of doing this?

cs95
  • 379,657
  • 97
  • 704
  • 746
Vash
  • 704
  • 1
  • 7
  • 19
  • 5
    See also Eric Lippert's [guide to doing an integer division problem](https://stackoverflow.com/a/926806/65839). It's a different problem, but you should probably take a similar approach to defining your requirements and only then writing code in such a way that it is obviously correct. –  Jul 18 '17 at 16:48
  • 8
    Never use `parseInt` when you actually mean `Math.floor`. – Bergi Jul 18 '17 at 21:02
  • @Mehrdad It's a mix of some factors: pure `javascript` tag questions are becoming incredibly simple (OP does zero research) or boring, the time of the day the question was posted, the mood of the people at that time... When I [left a comment](https://stackoverflow.com/questions/45164645/how-to-separate-a-number-into-2-addends#comment77298004_45165028) here it had just 6 upvotes, but in a short time span. Then, the question was listed in the "Hot network question". From that point on it was a snowball effect (or a positive feedback if you like). – Gerardo Furtado Jul 19 '17 at 12:55
  • 1
    Why can't it be 5,1 and 6,1 ? – Tom Taylor Jul 20 '17 at 18:38

10 Answers10

107

Just find the first part and subtract it from the original number.

var x = 7;

var p1 = Math.floor(x / 2);
var p2 = x - p1;

console.log(p1, p2);

In the case of x being odd, p1 will receive the smaller of the two addends. You can switch this around by calling Math.ceil instead.

cs95
  • 379,657
  • 97
  • 704
  • 746
  • 8
    I think you want to use `Math.floor` or `Math.ceil` explicitly when want the first to be the smaller/larger one. `round` makes it ambiguous. – Bergi Jul 18 '17 at 21:03
  • 3
    @cᴏʟᴅsᴘᴇᴇᴅ then use Math.ceil - which you don't even have to think about to know it will round up, and will still round up even if e.g. The divisor changes. – OrangeDog Jul 18 '17 at 22:07
  • @OrangeDog Alright. Footnote added. Thanks for the input :) – cs95 Jul 18 '17 at 22:10
  • 3
    And Math.ceil is shorter and therefore counts for more points if this were over on code golf. :) – DonielF Jul 19 '17 at 01:16
  • @hvd Apparently that doesn't work for negative integers and positive ones beyond 2^32, I think. – cs95 Jul 19 '17 at 05:46
  • @cᴏʟᴅsᴘᴇᴇᴅ It does work for negative integers. Beyond 2^32, it indeed doesn't work, but by the usual code golf rules, that's okay. –  Jul 19 '17 at 05:48
  • 2
    As usual with floating point numbers, this requires some more care. Try `x = 1.2` – georg Jul 19 '17 at 09:55
  • 3
    @georg Should probably change the question title to "How to separate a _whole_ number into 2 addends?" ;) – cs95 Jul 19 '17 at 09:57
  • @cᴏʟᴅsᴘᴇᴇᴅ: that's an interesting line of thinking, but I'd suggest fixing the answer rather than the question. `0.6+0.6=1.2`, so `yourFunc(1.2)` should give `0.6 0.6`. This is a bit trickier but possible. – georg Jul 19 '17 at 10:02
  • 4
    @georg It's definitely worth putting as an answer, but if OP wanted to deal in floats, 7 would become `3.5 3.5`, not `4 3`. What I'm saying is that's out of the scope of the question, and I'm not sure how beneficial it'd be to actually answer that and complicate the existing solution here than, say, make a new question. – cs95 Jul 19 '17 at 10:05
  • It's up to you of course whether you fix your answer or not, but I personally prefer good answers on StackOverflow rather than "good enough" ones. – georg Jul 19 '17 at 13:38
  • @georg Fair enough, but I don't believe the answer to 1.2 should be `0.6 0.6`. Keeping up with the spirit of this question, I feel it should be `1 0.2`. Similarly, 7.25 would be `4.25, 3`, not `3.625 3.625`. What do you think? (the question of floats is already open to multiple interpretations... do you see the problem with answering it here?) – cs95 Jul 19 '17 at 14:49
  • 1
    @cᴏʟᴅsᴘᴇᴇᴅ: A "natural" generalization would be that the summands can only differ by the last digit, that is `7.25=3.62+3.63` – georg Jul 19 '17 at 19:06
  • @georg Okay. Added a solution that works for both floats and integers. – cs95 Jul 19 '17 at 19:28
  • @cᴏʟᴅsᴘᴇᴇᴅ: good one, but how about `7.125`, `7.12345` etc? ;) – georg Jul 20 '17 at 02:36
  • @georg Sorry, I don't believe I can meet your expectations :( – cs95 Jul 20 '17 at 04:34
  • 5
    @georg why do you insist on changing OP's expectations? Code in question doesn't work for floating point numbers too but OP is fine with it ("This does what I want") – barbsan May 18 '18 at 13:35
38

Let javascript do Math for you.

var x = 7;
var p1 = Math.ceil(x / 2);
var p2 = Math.floor(x / 2);
console.log(p1, p2);
Andrii Abramov
  • 10,019
  • 9
  • 74
  • 96
Suresh Atta
  • 120,458
  • 37
  • 198
  • 307
  • 1
    Just wondering : since Javascript only has floats and not integers, couldn't this method lead to different values for `p1` and `p2` even if `x` is even? – Eric Duminil Jul 18 '17 at 13:07
  • 8
    @EricDuminil `/2` in IEEE floating point cannot cause a loss of precision or rounding in any integer that can be represented as a floating point prior to /2. It simply involves subtracting 1 from the exponent portion. – Yakk - Adam Nevraumont Jul 18 '17 at 14:37
  • @Yakk: You can lose data for subnormal numbers, because /2 will shift the significant right by one bit instead of changing the exponent. However, subnormal numbers are smaller than one so they probably don't matter for this question (they are not integers). – Kevin Jul 18 '17 at 17:29
  • 1
    @Kevin Yes, quite. I said for "any integer that can be represented as a floating point" for a reason. Subnormal numbers are not representations of any integer as floating point numbers. Thus are not relevant to my comment (and, as you noted, not relevant to this question either). – Yakk - Adam Nevraumont Jul 18 '17 at 17:32
  • 1
    FWIW, this gives `1 0` for `x=1.5`. – georg Jul 19 '17 at 09:57
  • @georg While true, I really haven't checked the corner cases and just checked with what OP asked for. Thanks for pointing though. – Suresh Atta Jul 19 '17 at 10:05
8

Your code can be simplified a bit:

var num = 7;
var p1 = Math.floor(num / 2);
var p2 = p1;

if (num % 2 != 0) {
   p1++;
}
console.log(p1, p2);
Abdul Rauf
  • 766
  • 2
  • 7
  • 19
  • 6
    If num is a number, and therefore num / 2 is also a number, why are you using parseInt (a function intended to convert a string to a number)? (I know why, but I think your answer would benefit massively from explaining why you've done it and what particular quirk of parseInt you're relying on to make it work.) – Anthony Grist Jul 18 '17 at 12:38
  • 3
    Honestly, `var p2 = p1;` is far less wasteful than calling `parseInt` twice. – cs95 Jul 18 '17 at 17:30
  • 1
    Also, use `parseInt` only when you have a string. It does not work on numbers. – Bergi Jul 18 '17 at 21:06
  • @Bergi It works on numbers also. But the number will be first converted to a string and then parsed to get a integer. Check this: http://www.jibbering.com/faq/faq_notes/type_convert.html#tcParseIn – Abdul Rauf Jul 19 '17 at 05:16
  • @AnthonyGrist I was using parseInt just to convert float into a int. My answer does not rely on any other quirk of parseInt. I don't have much experience in JS as it is not my primary language. I have updated my answer now. Thanks. – Abdul Rauf Jul 19 '17 at 05:30
  • @arauf Yes, and since it does not work on all numbers - as explained in the FAQ you linked - I consider it to not work at all. – Bergi Jul 19 '17 at 06:00
  • @Bergi yes, it will give wrong result when a non-numeric character is encountered. it is better to not use parseInt with numbers. – Abdul Rauf Jul 19 '17 at 06:09
  • @arauf The passed value is converted to a string. The parseInt function simply stops parsing - rather than throwing an exception - when it encounters a non-numeric character in the string. Those are both particular quirks of the JavaScript implementation of parseInt that your answer relies on to work. – Anthony Grist Jul 19 '17 at 07:56
4

var num = 7;

var part1 = parseInt(num/2);
var part2 = num - part1;

console.log(part1, part2);
Tom Taylor
  • 3,344
  • 2
  • 38
  • 63
4

Another way to do this is using bitwise operators. It doesn't work for very big numbers

function splitter(number){
  part1 = (number>>1) + (number&1);
  part2 = number>>1;
  console.log(number + ":", part1 + "+" + part2);
}

splitter(7);
splitter(6);
splitter(2**30+1); // Breaks for values greater than 2**31
splitter(2**31+1); 
TheChetan
  • 4,440
  • 3
  • 32
  • 41
3

var x = 11;             
var a = Math.ceil(x/2);   
var b = x-a;             

console.log("x = " + x + " , a = " + a + " , b = " + b);
cs95
  • 379,657
  • 97
  • 704
  • 746
Ali Faris
  • 17,754
  • 10
  • 45
  • 70
2

If in-case you don't want your outputs to be consecutive or exact identical and yet want to 'separate an integer into two numbers', this is the solution for you:

function printSeparatedInts(num) {
  let smallerNum = Math.floor(Math.random() * Math.floor(num));
  if (num && smallerNum === (num/2)) {    // checking if input != 0 & output is not consecutive
    printSeparatedInts(num)
   } else {
    console.log(smallerNum, (num - smallerNum))
  }
}

printSeparatedInts(22)
printSeparatedInts(22)     // will likely print different output from above
printSeparatedInts(7)
BlackBeard
  • 10,246
  • 7
  • 52
  • 62
0

Feeling lazy ? No problem !

I proudly present to you a generator object !

Initialize it and just use it! It will automatically change value every other use, even in the same line!!

Usage: a = new splitter(n) then console.log(a+" and "+a)

function splitter(n){
    this.p1 = Math.floor(n/2);
    this.p2 = n-this.p1;
    this.cnt=0;
    this.valueOf= ()=> (++this.cnt%2)? this.p1:this.p2;
    return n;
}

a = new splitter(5);
console.log(a + " and " +a);
console.log(a + " and " +a);
console.log(a + " and " +a);

b = new splitter(11);
console.log(b + " and " +b);
Community
  • 1
  • 1
Attersson
  • 4,755
  • 1
  • 15
  • 29
0
var number = 7;
var part1 = 0;
var part2 = 0;

if(number == 0) {
    part1 = (part2 = 0);
    console.log(part1, part2);
}
else if(number == 1) {
    part1 = 1;
    part2 = 0;
    console.log(part1, part2);
}
else if((number % 2) == 0) {
    part1 = part2 = number / 2;
    console.log(part1, part2);
}
else {
    part1 = (number + 1) / 2;
    part2 = number - part1;
    console.log(part1, part2);
}

Only other solution, I think performance is OK.

chaunv
  • 833
  • 6
  • 15
-2

Or this way :)

var number = 7;
var part1 = ~~((number / 2) + (number % 2));
var part2 = ~~(number / 2);

console.log(part1, part2);
Dennisch
  • 6,888
  • 1
  • 17
  • 32