493

I’d like to see integers, positive or negative, in binary.

Rather like this question, but for JavaScript.

Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
barlop
  • 12,887
  • 8
  • 80
  • 109
  • 3
    the a.toString(2) examples don't seem to work for -1 – barlop Mar 30 '12 at 09:01
  • 1
    It's also possible to convert from binary to decimal: http://stackoverflow.com/questions/11103487/convert-binary-representation-of-number-from-string-to-int-javascript – Anderson Green Jan 21 '13 at 21:52
  • And when I said "in binary", that may be a bit ambiguous. I mean the internal bit string representation, which is 2s complement, so positive numbers would be in base 2, and with a leading 0, (and negative numbers wouldn't be written with a minus symbol or with sign magnitude representation, but as a function of their positive eqivalent) – barlop Jun 05 '19 at 09:37
  • This question is incredibly misleading. "Maybe a bit ambiguous" is put too mildly. Why is 2s complement not appearing in the title nor in the body of the question, if that is the thing you actually want? Neither is a more or less equivalent expression like 'internal bit-string-representation'. From your answer and your comments on other answers I conclude you don't care about binary but rather about 2s complement. The questions you criticize look to me as if they answered _exactly_ your question... It's not those answers that are bad - your question is. – dingalapadum Jan 11 '21 at 16:22
  • @dingalapadum Well consider this. How many different ways (in practise), do computers represent positive and negative integers? There's the sign magnitude method, there's 1s complement, and 2s complement. And there's "some custom method". If somebody is going to show a way, then they should state the name of the representation. If somebody writes "-1101" that's not binary is it. 'cos a minus sign is not a binary digit. If somebody is going to say that 1 is "1" and -1 is "11111" well, what's the mechanical way you are distinguishing these. What's the name of that system. – barlop Jan 11 '21 at 20:09
  • When we talk about representation of numbers in „x-ary“, we mean that we use x digits to represent the _magnitude_ of the number. The sign of the number is not a digit and is not used for the magnitude. The sign also does not change the magnitude of the number. What you are asking about, has to do with how to encode numbers in a binary string. In the comment you are already saying you care about 2s complement. So, why not put it in the title or in the question itself, to avoid misleading people, avoiding this discussion, make the question clearer and of higher quality overall? – dingalapadum Jan 11 '21 at 21:17
  • @dingalapadum You are just spewing further red herrings, for example, you write , as some kind of argument to me, that "1011 can be understood as binary number " (As if that is meant to be news or that I suggested otherwise). – barlop Jan 11 '21 at 21:53
  • I wrote „-1011“ not „1011“. negative numbers seem to be your whole issue with the ‚wrong‘ answers, right? Anyway. IMO it is a very poor quality question as it stands and it would be really simple to improve. I was just trying to explain why I think so. The ‚wrong‘ answers and your own comments support this. OTOH You still have not argued why it is better not to mention 2s complement in the title or body of the question. Asking for ‚how to convert to binary‘ but actually requiring 2s complement as an answer is (in your own words) _ambiguous_. Why not just make the question precise then? – dingalapadum Jan 11 '21 at 23:28
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/227175/discussion-between-barlop-and-dingalapadum). – barlop Jan 12 '21 at 02:30
  • What actually is negative zero in binary in javascript? It can only be in 1s complement? It is usually represented as all binary 1s. - > 111111111.... not sure how many. This reference has 32bit number binary representation of -0 as 1 followed by 31 zeros. - https://en.wikipedia.org/wiki/Signed_zero – JoePythonKing Feb 04 '21 at 20:05
  • @JoePythonKing What do you mean " It can only be in 1s complement?" You are from the UK so maybe you can write better in English. You can look up -1 in 1s complement or -1 in 2s complement. Computers tend to use 2s complement over 1s complement but it's no mystery to go from one to the other. There are some other representations out there. As for how many 1s when it comes to negative numbers, in eg 2s complement , it doesn't matter and probably wouldn't matter for 1s complement either. It depends how many bits you have to store the number! – barlop Mar 11 '21 at 21:44

17 Answers17

794

function dec2bin(dec) {
  return (dec >>> 0).toString(2);
}

console.log(dec2bin(1)); // 1
console.log(dec2bin(-1)); // 11111111111111111111111111111111
console.log(dec2bin(256)); // 100000000
console.log(dec2bin(-256)); // 11111111111111111111111100000000

You can use Number.toString(2) function, but it has some problems when representing negative numbers. For example, (-1).toString(2) output is "-1".

To fix this issue, you can use the unsigned right shift bitwise operator (>>>) to coerce your number to an unsigned integer.

If you run (-1 >>> 0).toString(2) you will shift your number 0 bits to the right, which doesn't change the number itself but it will be represented as an unsigned integer. The code above will output "11111111111111111111111111111111" correctly.

This question has further explanation.

-3 >>> 0 (right logical shift) coerces its arguments to unsigned integers, which is why you get the 32-bit two's complement representation of -3.

fernandosavio
  • 9,849
  • 4
  • 24
  • 34
  • 11
    [Here](http://stackoverflow.com/questions/16155592/negative-numbers-to-binary-string) is the explanation – fernandosavio Jul 26 '13 at 14:44
  • been a while since I tried javascript but trying it here http://www.w3schools.com/js/tryit.asp?filename=tryjs_output_alert with this yeah it worked – barlop Apr 10 '15 at 10:35
  • 2
    toString(2) doesn't work because you are getting the input from text. Use this: function decToBase(dec, base){ return parseInt(dec).toString(base); } alert(decToBase(dec, 2)); – Magus May 29 '15 at 13:47
  • 1
    You are assuming that the input is text, but the function in the answer expect a integer... So, if input is a text just convert it to integer, use the fake bitshift and it's done – fernandosavio May 30 '15 at 18:30
  • @Magus who is getting the input from text?! – barlop Jun 02 '15 at 09:58
  • @barlop when you get the value from any input its type defaults to text, that's what I assumed the other guy is doing, probably getting it's input from the user which would give you a, for example, "10". That's why I suggested the parseInt, the bitwise operation suggested works because it uses a specific operator(>>>) that results into a integer, if he did it with the + operator then it would concatenate a "0" because the first number type would be a string. parsetInt() is more readable, just that. – Magus Jun 03 '15 at 23:42
  • @Magus this was a specific technical question not about user input. No1 is taking user input,there is no text here n if there was then no1 is scratching their head trying2figure out how2convert a string 2an int, this question is beyond that.Obviously if they did take user input and so got a string then they can use parseInt but that obviously wasn't the question.The q got2the crux of a problem and that is how a question should be.The Qgave the purest form of the problem and got a pure answer.Hence I commented (-3 >>> 0).toString(2) does it.Every ans understood that other than your comment – barlop Jun 04 '15 at 00:13
  • @barlop I was making the answer better. Since it's javascript there are people that may come here needing to know why the .toString(2) was not working. And that was my case, I needed that function form an app in phonegap and it didn't work for me then I figured it was because I was getting the input from a text field and came back to share what I've learned. That's what the comments are for. That's how programming works, there is more then one correct answer to the same problem and I've provided one more way to solve it. In my view, better then a bitwise because it's clearer. Don't be mad. – Magus Jun 04 '15 at 04:55
  • @fernandosavio can you explain, or provide an article where I can see what ```>>>``` means? I have never seen it before – Paul Fitzgerald Jun 17 '15 at 22:25
  • @PaulFitzgerald, it is bit shift operations... [Here](https://en.wikipedia.org/wiki/Bitwise_operations_in_C#Shift_operators) and [here](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_shift_operators) are good articles about it.. – fernandosavio Jun 18 '15 at 12:33
  • Your answer is so unconcisely written, that a wrong answer actually got 20 more upvots than yours. You haven't shown what -3 looks like in binary, and the whole edit about parseInt (for one commenter that is taking input from a textbox and doesn't know how to convert strings to numbers) is a big distraction that makes it look like you are fixing a broken answer. I'll leave your answer as accepted though, because you found the answer and yours is the answer. `(-3>>>0).toString(2);` prints `11111101` which is -3 in 2s complement. – barlop Nov 17 '15 at 14:05
  • further explanations here http://stackoverflow.com/questions/1822350/what-is-the-javascript-operator-and-how-do-you-use-it – barlop Feb 18 '16 at 09:58
  • can do quick test of `javascript:alert((-3>>>0).toString(2));` <-- in address bar – barlop Jul 01 '17 at 12:28
  • `11111111111111111111111111111101` on Firefox and Chrome. Why? – fernandosavio Jul 01 '17 at 18:34
  • @fernandosavio because that's the answer, that is -3 in 2s complement. To get -3 you take 3, then invert the bits and add 1. So 0011 becomes 1100 which becomes 1101 – barlop Jul 01 '17 at 21:27
  • Yeah, I know it is the correct answer. I just didn't get why test the answer now, I've tested when I posted. :) – fernandosavio Jul 03 '17 at 12:10
  • @fernandosavio Be careful when you edit. When you first wrote the answer it was so bad that a wrong answer got more votes. It was only after I edited your answer that it got more votes than the wrong answer. Would you let me remove the entire addressing magus part? Also making a function as you did was pointless when you could've done just one line like in my example. Can I remove the magus part? Can I remove your function and just use that single line example? That would improve things a lot. Removing the magus part would be the main improvement, if you at least let me do that. – barlop Jul 23 '17 at 16:30
  • @barlop I've edited the question, I think it is much better now. Fell free to improve it if you want. – fernandosavio Jul 24 '17 at 17:40
  • Where you wrote `-3 >>> 0 (right logical shift) coerces its arguments to unsigned integers, which is why you get the 32-bit two's complement representation of -3.` It actually explains very little and in fact, 2s complement is SIGNED, so to say you're getting an unsigned integer is really unclear. – barlop Jul 24 '17 at 21:37
  • My point about the fact that the result isn't really proper 2s complement and technically the result is wrong.. unless you ensure positive numbers have a leading 0. You don't make that point clearly by stating at the end to pad accordingly, which says nothing about 2s complement, nothing about the result not really being correct without , and nothing about leading 0 for positive numbers, and just saying "accordingly" says nothing about what to do for the correct answer – barlop Jul 24 '17 at 21:38
  • Also not only have you removed the important point about the result being wrong for not having the leading 0 for positive numbers, there is another answer or two , one of which is simple and they don't have that mistake, so I have changed that one to the accept answer. – barlop Jul 24 '17 at 21:41
  • An improvement to get that important 0 at the beginning of positive numbers, would be (and you can make x= whatever number), amending first line accordingly `x=536870912; if(x>0) prepend="0"; else prepend=""; alert(prepend+((x>>>0)).toString(2).toString());` I have mentioned this in my answer, that gets the correct result with >>> – barlop Jul 24 '17 at 22:24
  • Also you presented a significant problem as if it was a formatting issue (padding with zeros), and as a Note 2, secondary to what you called Note 1 which was your response to that Magus commenter that had a string from textbox that was irrelevant to the question. – barlop Jul 25 '17 at 14:36
  • `x >>> 0` does the same as `~x`; – SparK Sep 18 '17 at 23:34
  • Nope. `~x` is binary not, `x >>> 0` is a bitshift operator which shift 0 bits to right. In this case it will just coerce the number to a unsigned 32 bit integer... – fernandosavio Sep 20 '17 at 00:35
  • on 6449281454 got 10000000011010000011100110101110 but answer is 110000000011010000011100110101110 – Дан Воронов Nov 28 '21 at 19:08
  • As mentioned in the answer the result is coerced to a 32bit unsigned int, so the upper limit will be `Math.pow(2, 32)` which is `4294967296`. That's why you are getting the wrong number. Thanks for the comment, it will help future visitors on this matter. :) – fernandosavio Nov 30 '21 at 14:22
303

Try

num.toString(2);

The 2 is the radix and can be any base between 2 and 36

source here

UPDATE:

This will only work for positive numbers, Javascript represents negative binary integers in two's-complement notation. I made this little function which should do the trick, I haven't tested it out properly:

function dec2Bin(dec)
{
    if(dec >= 0) {
        return dec.toString(2);
    }
    else {
        /* Here you could represent the number in 2s compliment but this is not what 
           JS uses as its not sure how many bits are in your number range. There are 
           some suggestions https://stackoverflow.com/questions/10936600/javascript-decimal-to-binary-64-bit 
        */
        return (~dec).toString(2);
    }
}

I had some help from here

Community
  • 1
  • 1
Manatok
  • 5,506
  • 3
  • 23
  • 32
  • 1
    doesn't work for -1. a=-1; document.write(Number(a.toString(2))); displays -1 – barlop Mar 30 '12 at 09:05
  • The update still doesn't appear to work for negative numbers (`-3` returns `1`). Also I believe `dec > 0` should be `dec >= 0`, which should at least fix 0. Because `dec2Bin(0)` returns `10`. – Adam Merrifield Apr 15 '14 at 21:17
  • Both cases in above comments return correct result in my chrome console - var a = -1; a.toString(2); "-1" var a = -3; a.toString(2); "-11" – Anmol Saraf Jul 09 '14 at 12:01
  • @AnmolSaraf I see what you mean, and while colloquially when people say what is -5 in decimal, and the answer is -5 When it comes to negative numbers in binary , in a sense yeah you could stick a minus sign there so 5 is 101 and -5 is -101 but since computers don't store minus signs, they just represent 1s and 0s, so when we say negative numbers in binary, we really mean putting the negative number (minus sign included) in 1s and 0s. Some ways include 1s complement, 2s complement, and 'sign and magnitude'. So -101010101 or -0101010 is not what people mean by a negative number in binary. – barlop Apr 10 '15 at 10:59
  • This link may be of interest to some http://stackoverflow.com/questions/12337360/javascript-tilde-twos-complement anyhow, Your answer contradicts itself, you write "Javascript represents negative binary integers in two's-complement notation." And your code says " Here you could represent the number in 2s compliment but this is not what JS as uses as [nonsense reason] " And you give no reference either. – barlop Feb 22 '16 at 12:05
  • To me, a negative number should just have a negative binary representation. So the bottom part should be return "-" + (-dec).toString(2); – Luc Bloom Dec 06 '20 at 21:15
89

A simple way is just...

Number(42).toString(2);

// "101010"
Igor
  • 33,276
  • 14
  • 79
  • 112
ad rees
  • 1,522
  • 2
  • 11
  • 16
  • 33
    I would prefer `(42).toString(2)` – Willem D'Haeseleer Apr 15 '14 at 16:57
  • 45
    Or even shorter `42..toString(2)` – kapex Jul 26 '14 at 02:38
  • 10
    People are struggling with this. The answer is correct because it casts the input (42) to an integer and that line is needed. If you get your 'number' from an text input the toString(2) wouldn't work. – Magus Jun 03 '15 at 23:46
  • @Magus The .toString won't answer my question as it doesn't work for negatives. And if he did do toString, he can do `42..toString(2)` and there's probably no casting of int to int by Number(42) as 42 is an integer anyway so it likely leaves it as it is. Secondly, the thing you say people are struggling with (converting a string to an integer), people are not and it's not in this question, and what you keep bringing up as news to you, is a – barlop Jun 05 '15 at 23:36
  • @Magus (cntd) really basic thing about programming languages, that if u r dealing with a string like "123" then one often has to convert that to an integer (or decimal) even to add one to it, forget even this. The problem you struggled with you'd even struggle to increment your "number" by 1 forget converting it to binary. – barlop Jun 05 '15 at 23:38
  • 1
    @barlop I give up. Here, have a cookie. – Magus Jun 07 '15 at 00:19
  • 5
    @Kapep, Dude that's genius. How did you know about that? – Pacerier Feb 17 '17 at 04:30
  • As Annan has explained to Magus, the x.toString(2) method doesn't give a binary string when x is negative. – barlop Jul 24 '17 at 22:31
  • @kapex can you explain what kind of mechanism work in your example ? – suchcodemuchwow Dec 11 '18 at 21:08
  • 7
    @BatuG. The syntax for numbers allows you to omit the part after the decimal separator. You can write `1.` which is the same as `1.0` or just `1` (and similarly you can also omit the part before and write `.5` instead of `0.5`). So in the example the first dot is the decimal separator which is part of the number and the second dot is the dot operator for calling the method on that number. You have to use two dots (or wrap the number in parenthesis) and can't just write `42.toString(2)` because the parser sees the dot as decimal separator and throws an error because of a missing dot operator. – kapex Dec 12 '18 at 08:47
60

The binary in 'convert to binary' can refer to three main things. The positional number system, the binary representation in memory or 32bit bitstrings. (for 64bit bitstrings see Patrick Roberts' answer)

1. Number System

(123456).toString(2) will convert numbers to the base 2 positional numeral system. In this system negative numbers are written with minus signs just like in decimal.

2. Internal Representation

The internal representation of numbers is 64 bit floating point and some limitations are discussed in this answer. There is no easy way to create a bit-string representation of this in javascript nor access specific bits.

3. Masks & Bitwise Operators

MDN has a good overview of how bitwise operators work. Importantly:

Bitwise operators treat their operands as a sequence of 32 bits (zeros and ones)

Before operations are applied the 64 bit floating points numbers are cast to 32 bit signed integers. After they are converted back.

Here is the MDN example code for converting numbers into 32-bit strings.

function createBinaryString (nMask) {
  // nMask must be between -2147483648 and 2147483647
  for (var nFlag = 0, nShifted = nMask, sMask = ""; nFlag < 32;
       nFlag++, sMask += String(nShifted >>> 31), nShifted <<= 1);
  return sMask;
}

createBinaryString(0) //-> "00000000000000000000000000000000"
createBinaryString(123) //-> "00000000000000000000000001111011"
createBinaryString(-1) //-> "11111111111111111111111111111111"
createBinaryString(-1123456) //-> "11111111111011101101101110000000"
createBinaryString(0x7fffffff) //-> "01111111111111111111111111111111"
AnnanFay
  • 9,573
  • 15
  • 63
  • 86
  • 1
    What is the advantage of using this function instead of using a simple Number(num).toString(2) ? – Magus Jun 03 '15 at 23:50
  • 6
    @Magus I think I explain adequately the differences between numerals and binary strings. A 32 bit binary string is always thirty-two characters long comprised of "1"s and "0"s. toString returns an *actual* number represented using the positional number systems with the given base. It depends *why* you want the string, they have very different meanings. – AnnanFay Jun 04 '15 at 03:07
  • sorry, you are right. I jumped straight to the code. – Magus Jun 04 '15 at 04:56
  • 1
    Had an issue with leading 0s using the other posted methods (specifically on this number 536870912, the two leading zeroes are removed), but this solution handled it correctly. – UberMouse Aug 05 '15 at 04:17
  • @UberMouse yeah the >>> has the leading 0s issue, i'll accept this one. – barlop Jul 24 '17 at 21:41
  • I have accepted this answer because it doesn't have the missing 0 issue. And i've added two notes.. But where you wrote regarding .toString(2), "it converts numbers to the base 2 positional numeral system. In this system just like in decimal." Are you sure that 2s complement isn't also a base 2 positional numeral system?! – barlop Jul 24 '17 at 22:01
  • @UberMouse yes that is right.. how about `x=536870912; if(x>0) prepend="0"; else prepend=""; alert(prepend+((x>>>0)).toString(2).toString());` – barlop Jul 24 '17 at 22:23
  • @barlop Yes. The phrase 'convert to binary' can refer to the positional number system **or** bitstrings **or** internal representation (hence the three sections in my answer). This positional system is exactly the same as decimal however uses radix 2. Thus it can display negative and floating point numbers, for example `-2.25 (decimal)` becomes `-10.01 (binary)`. I linked to the wikipedia article which adequately explains positional number systems. No offense but I will roll back your edits as several are better left to comments. If there is something you wish me readd please say. – AnnanFay Jul 25 '17 at 02:40
  • @Annan You write "The phrase 'convert to binary' can refer to the positional number system or bitstrings or internal representation" <-- it's not clear to me whether you're trying to say those are all the same thing, or an either or, but neither would be correct. The internal representation is a bit string that uses the positional numbering system! – barlop Jul 25 '17 at 03:09
  • @barlop They are different. "The internal representation is a bit string that uses the positional numbering system!": Nope. – AnnanFay Jul 25 '17 at 03:10
  • @Annan then it's not clear to me whether you're trying to say they're alternatives, like "either or" options. – barlop Jul 25 '17 at 03:12
  • Also you wrote "(123456).toString(2) will convert numbers to the base 2 positional numeral system. In this system negative numbers are written with minus signs just like in decimal." <--- If it gives a minus sign followed by a decimal number then there it clearly isn't showing a number converted to base 2. – barlop Jul 25 '17 at 03:13
  • @barlop They are homonyms. – AnnanFay Jul 25 '17 at 03:14
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/150043/discussion-between-barlop-and-annan). – barlop Jul 25 '17 at 03:14
35

This answer attempts to address inputs with an absolute value in the range of 214748364810 (231) – 900719925474099110 (253-1).


In JavaScript, numbers are stored in 64-bit floating point representation, but bitwise operations coerce them to 32-bit integers in two's complement format, so any approach which uses bitwise operations restricts the range of output to -214748364810 (-231) – 214748364710 (231-1).

However, if bitwise operations are avoided and the 64-bit floating point representation is preserved by using only mathematical operations, we can reliably convert any safe integer to 64-bit two's complement binary notation by sign-extending the 53-bit twosComplement:

function toBinary (value) {
  if (!Number.isSafeInteger(value)) {
    throw new TypeError('value must be a safe integer');
  }

  const negative = value < 0;
  const twosComplement = negative ? Number.MAX_SAFE_INTEGER + value + 1 : value;
  const signExtend = negative ? '1' : '0';

  return twosComplement.toString(2).padStart(53, '0').padStart(64, signExtend);
}

function format (value) {
  console.log(value.toString().padStart(64));
  console.log(value.toString(2).padStart(64));
  console.log(toBinary(value));
}

format(8);
format(-8);
format(2**33-1);
format(-(2**33-1));
format(2**53-1);
format(-(2**53-1));
format(2**52);
format(-(2**52));
format(2**52+1);
format(-(2**52+1));
.as-console-wrapper{max-height:100%!important}

For older browsers, polyfills exist for the following functions and values:

As an added bonus, you can support any radix (2–36) if you perform the two's complement conversion for negative numbers in ⌈64 / log2(radix)⌉ digits by using BigInt:

function toRadix (value, radix) {
  if (!Number.isSafeInteger(value)) {
    throw new TypeError('value must be a safe integer');
  }

  const digits = Math.ceil(64 / Math.log2(radix));
  const twosComplement = value < 0
    ? BigInt(radix) ** BigInt(digits) + BigInt(value)
    : value;

  return twosComplement.toString(radix).padStart(digits, '0');
}

console.log(toRadix(0xcba9876543210, 2));
console.log(toRadix(-0xcba9876543210, 2));
console.log(toRadix(0xcba9876543210, 16));
console.log(toRadix(-0xcba9876543210, 16));
console.log(toRadix(0x1032547698bac, 2));
console.log(toRadix(-0x1032547698bac, 2));
console.log(toRadix(0x1032547698bac, 16));
console.log(toRadix(-0x1032547698bac, 16));
.as-console-wrapper{max-height:100%!important}

If you are interested in my old answer that used an ArrayBuffer to create a union between a Float64Array and a Uint16Array, please refer to this answer's revision history.

Community
  • 1
  • 1
Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
  • Thanks, it is good that this works for 64bit.. Can you let me know any advantages of this answer over annan's answer? – barlop Jul 24 '17 at 21:51
  • 3
    Much larger range? It works for `-(2**53)-1` to `2**53-1` instead of just `-(2**31)` to `2**31-1` like annan's answer. – Patrick Roberts Jul 24 '17 at 22:01
  • Yes that is a big advantage, I get that, and that will do, though it is quite a bit more code, but what I meant was, i'm curious if any other advantages? – barlop Jul 25 '17 at 14:31
  • Thanks.. Also any thoughts on any advantages/disadvantages between the solution of these three lines `x=5; if(x>0) prepend="0"; else prepend=""; alert(prepend+((x>>>0)).toString(2).toString());` vs Annan's solution? – barlop Jul 25 '17 at 14:47
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/150103/discussion-between-barlop-and-patrick-roberts). – barlop Jul 25 '17 at 15:10
  • 1
    from 2**32+1 on, last (rightmost) bit is cleared when it should be set. – Lovro Nov 10 '18 at 17:25
  • 1
    Works when the line is: var exponent = ((uint16[3] & 0x7FF0) >> 4) - 1023 + 1; – Lovro Nov 10 '18 at 17:33
31

A solution i'd go with that's fine for 32-bits, is the code the end of this answer, which is from developer.mozilla.org(MDN), but with some lines added for A)formatting and B)checking that the number is in range.

Some suggested x.toString(2) which doesn't work for negatives, it just sticks a minus sign in there for them, which is no good.

Fernando mentioned a simple solution of (x>>>0).toString(2); which is fine for negatives, but has a slight issue when x is positive. It has the output starting with 1, which for positive numbers isn't proper 2s complement.

Anybody that doesn't understand the fact of positive numbers starting with 0 and negative numbers with 1, in 2s complement, could check this SO QnA on 2s complement. What is “2's Complement”?

A solution could involve prepending a 0 for positive numbers, which I did in an earlier revision of this answer. And one could accept sometimes having a 33bit number, or one could make sure that the number to convert is within range -(2^31)<=x<2^31-1. So the number is always 32bits. But rather than do that, you can go with this solution on mozilla.org

Patrick's answer and code is long and apparently works for 64-bit, but had a bug that a commenter found, and the commenter fixed patrick's bug, but patrick has some "magic number" in his code that he didn't comment about and has forgotten about and patrick no longer fully understands his own code / why it works.

Annan had some incorrect and unclear terminology but mentioned a solution by developer.mozilla.org

Note- the old link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators now redirects elsewhere and doesn't have that content but the proper old link , which comes up when archive.org retrieves pages!, is available here https://web.archive.org/web/20150315015832/https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators

The solution there works for 32-bit numbers.

The code is pretty compact, a function of three lines.

But I have added a regex to format the output in groups of 8 bits. Based on How to format a number with commas as thousands separators? (I just amended it from grouping it in 3s right to left and adding commas, to grouping in 8s right to left, and adding spaces)

And, while mozilla made a comment about the size of nMask(the number fed in)..that it has to be in range, they didn't test for or throw an error when the number is out of range, so i've added that.

I'm not sure why they named their parameter 'nMask' but i'll leave that as is.

https://web.archive.org/web/20150315015832/https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators

function createBinaryString(nMask) {
  // nMask must be between -2147483648 and 2147483647
  if (nMask > 2**31-1) 
     throw "number too large. number shouldn't be > 2**31-1"; //added
  if (nMask < -1*(2**31))
     throw "number too far negative, number shouldn't be < -(2**31)" //added
  for (var nFlag = 0, nShifted = nMask, sMask = ''; nFlag < 32;
       nFlag++, sMask += String(nShifted >>> 31), nShifted <<= 1);
  sMask=sMask.replace(/\B(?=(.{8})+(?!.))/g, " ") // added
  return sMask;
}


console.log(createBinaryString(-1))    // "11111111 11111111 11111111 11111111"
console.log(createBinaryString(1024))  // "00000000 00000000 00000100 00000000"
console.log(createBinaryString(-2))    // "11111111 11111111 11111111 11111110"
console.log(createBinaryString(-1024)) // "11111111 11111111 11111100 00000000"

//added further console.log example
console.log(createBinaryString(2**31 -1)) //"01111111 11111111 11111111 11111111"  
barlop
  • 12,887
  • 8
  • 80
  • 109
  • `nMask` name might be because the integer is treated as a _bitmask_, and nMask then refers to _multiple masks_ (a set of one or more masks, joined into one). See section "Automate Mask Creation": https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators – Magne Jun 24 '20 at 07:59
10

You can write your own function that returns an array of bits. Example how to convert number to bits

Divisor| Dividend| bits/remainder

2 | 9 | 1

2 | 4 | 0

2 | 2 | 0

~ | 1 |~

example of above line: 2 * 4 = 8 and remainder is 1 so 9 = 1 0 0 1

function numToBit(num){
    var number = num
    var result = []
    while(number >= 1 ){
        result.unshift(Math.floor(number%2))
        number = number/2
    }
    return result
}

Read remainders from bottom to top. Digit 1 in the middle to top.

supritshah1289
  • 839
  • 8
  • 15
5

This is how I manage to handle it:

const decbin = nbr => {
  if(nbr < 0){
     nbr = 0xFFFFFFFF + nbr + 1
  }
  return parseInt(nbr, 10).toString(2)
};

got it from this link: https://locutus.io/php/math/decbin/

barlop
  • 12,887
  • 8
  • 80
  • 109
gildniy
  • 3,528
  • 1
  • 33
  • 23
  • @barlop thanks for raising the issues, it's now edited – gildniy Aug 10 '20 at 07:17
  • 1
    can you explain the logic behind that code, how it works.. that by adding 0xFFFFFFFF+1 to negative numbers then it works... and if you got the code from somewhere can you link to a source? Thanks – barlop Aug 10 '20 at 10:18
  • @barlop, got it from this link: https://locutus.io/php/math/decbin/ – gildniy Aug 10 '20 at 10:28
2

we can also calculate the binary for positive or negative numbers as below:

function toBinary(n){
    let binary = "";
    if (n < 0) {
      n = n >>> 0;
    }
    while(Math.ceil(n/2) > 0){
        binary = n%2 + binary;
        n = Math.floor(n/2);
    }
    return binary;
}

console.log(toBinary(7));
console.log(toBinary(-7));
ganesh phirke
  • 471
  • 1
  • 3
  • 12
  • questioned wanted negative too – barlop Aug 26 '20 at 13:53
  • converted the negative numbers to unsigned representation. Now the logic will work for positive or negative numbers. Thanks @barlop – ganesh phirke Aug 27 '20 at 07:22
  • putting the positive numbers starting with 1 e.g. 7 as 111, are a problem. 'cos if you want positive numbers to start from 1, then how do you know what 111 is, whether it's 7 or -1. Your program puts -1 as `11111111111111111111111111111111` and 7 as `111`. In 2s complement, 1111111 and 111 are the same number. -1. – barlop Aug 27 '20 at 15:55
2

You could use a recursive solution:

function intToBinary(number, res = "") {
  if (number < 1)
    if (res === "") return "0"
      else 
     return res
  else return intToBinary(Math.floor(number / 2), number % 2 + res)
}
console.log(intToBinary(12))
console.log(intToBinary(546))
console.log(intToBinary(0))
console.log(intToBinary(125))
Works only with positive numbers.
Lars Flieger
  • 2,421
  • 1
  • 12
  • 34
2

An actual solution that logic can be implemented by any programming language:

If you sure it is positive only:

var a = 0;
var n = 12; // your input
var m = 1;
while(n) {
    a = a + n%2*m;
    n = Math.floor(n/2);
    m = m*10;
}

console.log(n, ':', a) // 12 : 1100

If can negative or positive -

(n >>> 0).toString(2)
Yadab Sd
  • 591
  • 4
  • 9
  • You haven't even read the first line of the question, which said for negative numbers too. Your solution doesn't work for negative numbers. – barlop May 12 '22 at 22:38
  • @barlop you should respect the ideal thing, not you're looking for. Js is a loosely language you know. you can easily do it by (n >>> 0).toString(2) – Yadab Sd May 14 '22 at 08:10
  • 1
    Try reading other answers instead of posting an answer that doesn't answer it(doesn't address negative numbers), then adjusting your answer with a copy of a solution that is mentioned in another answer, to do it for negatives. By the way, MDN has a solution too, but all that is mentioned in other answers, so you aren't adding anything here. – barlop Jul 06 '22 at 18:08
  • @barlop then you should search for similar answers instead of asking ... – Yadab Sd Jul 06 '22 at 18:11
  • What are you talking about. Nobody asked you anything. And this question was already answered long before you posted an answer – barlop Jul 06 '22 at 18:35
1

I’d like to see integers, positive or negative, in binary.

This is an old question and I think there are very nice solutions here but there is no explanation about the use of these clever solutions.

First, we need to understand that a number can be positive or negative. Also, JavaScript provides a MAX_SAFE_INTEGER constant that has a value of 9007199254740991. The reasoning behind that number is that JavaScript uses double-precision floating-point format numbers as specified in IEEE 754 and can only safely represent integers between -(2^53 - 1) and 2^53 - 1.

So, now we know the range where numbers are "safe". Also, JavaScript ES6 has the built-in method Number.isSafeInteger() to check if a number is a safe integer.

Logically, if we want to represent a number n as binary, this number needs a length of 53 bits, but for better presentation lets use 7 groups of 8 bits = 56 bits and fill the left side with 0 or 1 based on its sign using the padStart function.

Next, we need to handle positive and negative numbers: positive numbers will add 0s to the left while negative numbers will add 1s. Also, negative numbers will need a two's-complement representation. We can easily fix this by adding Number.MAX_SAFE_INTEGER + 1 to the number.

For example, we want to represent -3 as binary, lets assume that Number.MAX_SAFE_INTEGER is 00000000 11111111 (255) then Number.MAX_SAFE_INTEGER + 1 will be 00000001 00000000 (256). Now lets add the number Number.MAX_SAFE_INTEGER + 1 - 3 this will be 00000000 11111101 (253) but as we said we will fill with the left side with 1 like this 11111111 11111101 (-3), this represent -3 in binary.

Another algorithm will be we add 1 to the number and invert the sign like this -(-3 + 1) = 2 this will be 00000000 00000010 (2). Now we invert every bit like this 11111111 11111101 (-3) again we have a binary representation of -3.

Here we have a working snippet of these algos:

function dec2binA(n) {
    if (!Number.isSafeInteger(n)) throw new TypeError('n value must be a safe integer')
    if (n > 2**31) throw 'number too large. number should not be greater than 2**31'
    if (n < -1*(2**31)) throw 'number too far negative, number should not be lesser than 2**31'

    const bin = n < 0 ? Number.MAX_SAFE_INTEGER + 1 + n : n
    const signBit = n < 0 ? '1' : '0'

    return parseInt(bin, 10).toString(2)
        .padStart(56, signBit)
        .replace(/\B(?=(.{8})+(?!.))/g, ' ')
}


function dec2binB(n) {
    if (!Number.isSafeInteger(n)) throw new TypeError('n value must be a safe integer')
    if (n > 2**31) throw 'number too large. number should not be greater than 2**31'
    if (n < -1*(2**31)) throw 'number too far negative, number should not be lesser than 2**31'

    const bin = n < 0 ?  -(1 + n) : n
    const signBit = n < 0 ? '1' : '0'

    return parseInt(bin, 10).toString(2)
        .replace(/[01]/g, d => +!+d)
        .padStart(56, signBit)
        .replace(/\B(?=(.{8})+(?!.))/g, ' ')
}



const a = -805306368
console.log(a)
console.log('dec2binA:', dec2binA(a))
console.log('dec2binB:', dec2binB(a))

const b = -3
console.log(b)
console.log('dec2binA:', dec2binA(b))
console.log('dec2binB:', dec2binB(b))
Teocci
  • 7,189
  • 1
  • 50
  • 48
0

One more alternative

const decToBin = dec => {
  let bin = '';
  let f = false;

  while (!f) {
    bin = bin + (dec % 2);    
    dec = Math.trunc(dec / 2);  

    if (dec === 0 ) f = true;
  }

  return bin.split("").reverse().join("");
}

console.log(decToBin(0));
console.log(decToBin(1));
console.log(decToBin(2));
console.log(decToBin(3));
console.log(decToBin(4));
console.log(decToBin(5));
console.log(decToBin(6));
Ivan Proskuryakov
  • 1,625
  • 2
  • 23
  • 32
  • Please see Vincent's answer and the comment on it, it'd apply to your posting too – barlop Apr 26 '20 at 19:07
  • This is what was posted in comment on his answer, without disagreement, and with some agreement from others, "That may be useful for studying computer science to see how to do it manually, so as to teach yourself, but that is not what I am asking! If you are going to reinvent the wheel doing it manually like that, then it should be at least with the advantage of increased efficiency or some advantage like increase in the size of the values it can cope with. I don't see any discussion from you stating any such advantage there." – barlop Apr 26 '20 at 19:08
  • Furthermore, your solution completely fails, it makes positive numbers start with a 1 and completely fails for negative numbers, and my question mentioned positive or negative – barlop Apr 26 '20 at 19:11
  • So your "answer" is wrong on many many levels. And you should always review other answers before posting an answer – barlop Apr 26 '20 at 19:11
-1

I used a different approach to come up with something that does this. I've decided to not use this code in my project, but I thought I'd leave it somewhere relevant in case it is useful for someone.

  • Doesn't use bit-shifting or two's complement coercion.
  • You choose the number of bits that comes out (it checks for valid values of '8', '16', '32', but I suppose you could change that)
  • You choose whether to treat it as a signed or unsigned integer.
  • It will check for range issues given the combination of signed/unsigned and number of bits, though you'll want to improve the error handling.
  • It also has the "reverse" version of the function which converts the bits back to the int. You'll need that since there's probably nothing else that will interpret this output :D

function intToBitString(input, size, unsigned) {
 if ([8, 16, 32].indexOf(size) == -1) {
  throw "invalid params";
 }
 var min = unsigned ? 0 : - (2 ** size / 2);
        var limit = unsigned ? 2 ** size : 2 ** size / 2;
 if (!Number.isInteger(input) || input < min || input >= limit) {
  throw "out of range or not an int";
 }
 if (!unsigned) {
  input += limit;
 }
 var binary = input.toString(2).replace(/^-/, '');
 return binary.padStart(size, '0');
}

function bitStringToInt(input, size, unsigned) {
 if ([8, 16, 32].indexOf(size) == -1) {
  throw "invalid params";
 }
 input = parseInt(input, 2);
 if (!unsigned) {
  input -= 2 ** size / 2;
 }
 return input;
}


// EXAMPLES

var res;
console.log("(uint8)10");
res = intToBitString(10, 8, true);
console.log("intToBitString(res, 8, true)");
console.log(res);
console.log("reverse:", bitStringToInt(res, 8, true));
console.log("---");

console.log("(uint8)127");
res = intToBitString(127, 8, true);
console.log("intToBitString(res, 8, true)");
console.log(res);
console.log("reverse:", bitStringToInt(res, 8, true));
console.log("---");

console.log("(int8)127");
res = intToBitString(127, 8, false);
console.log("intToBitString(res, 8, false)");
console.log(res);
console.log("reverse:", bitStringToInt(res, 8, false));
console.log("---");

console.log("(int8)-128");
res = intToBitString(-128, 8, false);
console.log("intToBitString(res, 8, true)");
console.log(res);
console.log("reverse:", bitStringToInt(res, 8, true));
console.log("---");

console.log("(uint16)5000");
res = intToBitString(5000, 16, true);
console.log("intToBitString(res, 16, true)");
console.log(res);
console.log("reverse:", bitStringToInt(res, 16, true));
console.log("---");

console.log("(uint32)5000");
res = intToBitString(5000, 32, true);
console.log("intToBitString(res, 32, true)");
console.log(res);
console.log("reverse:", bitStringToInt(res, 32, true));
console.log("---");
braks
  • 1,505
  • 15
  • 23
  • doesn't your own test data fail, clearly -128 is not 00000000 – barlop Aug 26 '20 at 13:55
  • @barlop the signed data type int8 goes from -128 (00000000) to 127 (11111111), so this is as I've intended. My needs didn't need interoperability with another scheme. – braks Mar 14 '21 at 09:08
  • well if -128 is all zeros in your representations, then how are you going to be representing 0? – barlop Mar 12 '22 at 10:56
  • I'm sure if you put your mind to it you can figure it out – braks Mar 16 '22 at 14:51
  • look, -128 should not be all 000000 you have got it completely wrong and your claim about signed int being `-128 (00000000) to 127 (11111111)` is just made up and totally wrong.. – barlop Mar 16 '22 at 17:29
-1

This is a method that I use. It's a very fast and concise method that works for whole numbers.

If you want, this method also works with BigInts. You just have to change each 1 to 1n.

// Assuming {num} is a whole number
function toBin(num){
    let str = "";
    do {
        str = `${num & 1}${str}`;
        num >>= 1;
    } while(num);
    return str
}

Explanation

This method, in a way, goes through all the bits of the number as if it's already a binary number.

It starts with an empty string, and then it prepends the last bit. num & 1 will return the last bit of the number (1 or 0). num >>= 1 then removes the last bit and makes the second-to-last bit the new last bit. The process is repeated until all the bits have been read.

Of course, this is an extreme simplification of what's actually going on. But this is how I generalize it.

Diriector_Doc
  • 582
  • 1
  • 12
  • 28
  • your first sentence says ".toString(2) is probably your best bet.". -- Now try reading the first comment to the question. You see it says it only works for positive numbers. And try reading all the other answers that mention that issue with .toString(2). As for your function, it's interesting, you should state whether it works for positive numbers only, or for positive and negative numbers. – barlop Mar 12 '22 at 10:51
-2

This is my code:

var x = prompt("enter number", "7");
var i = 0;
var binaryvar = " ";

function add(n) {
    if (n == 0) {
        binaryvar = "0" + binaryvar; 
    }
    else {
        binaryvar = "1" + binaryvar;
    }
}

function binary() {
    while (i < 1) {
        if (x == 1) {
            add(1);
            document.write(binaryvar);
            break;
        }
        else {
            if (x % 2 == 0) {
                x = x / 2;
                add(0);
            }
            else {
                x = (x - 1) / 2;
                add(1);
            }
        }
    }
}

binary();
M0nst3R
  • 5,186
  • 1
  • 23
  • 36
  • 3
    That may be useful for studying computer science to see how to do it manually, so as to teach yourself, but that is not what I am asking! If you are going to reinvent the wheel doing it manually like that, then it should be at least with the advantage of increased efficiency or some advantage like increase in the size of the values it can cope with. I don't see any discussion from you stating any such advantage there. – barlop Nov 07 '17 at 15:41
-3

This is the solution . Its quite simple as a matter of fact

function binaries(num1){ 
        var str = num1.toString(2)
        return(console.log('The binary form of ' + num1 + ' is: ' + str))
     }
     binaries(3

)

        /*
         According to MDN, Number.prototype.toString() overrides 
         Object.prototype.toString() with the useful distinction that you can 
         pass in a single integer argument. This argument is an optional radix, 
         numbers 2 to 36 allowed.So in the example above, we’re passing in 2 to 
         get a string representation of the binary for the base 10 number 100, 
         i.e. 1100100.
        */
Brian
  • 5
  • 1
  • 1
    That solution has already been proposed many times and, as commented by OP already on Mar 30 '12 at 9:01, does not work for negative numbers. – Adrian W Jun 12 '18 at 08:25
  • 1
    @AdrianW I suggest downvoting this. I notice you haven't. What does it take for you to downvote an answer then?! – barlop Jun 12 '18 at 23:34