Як перетворити ціле число в двійкове в JavaScript?


299

Я хотів би бачити цілі числа, додатні чи негативні, у двійкових.

Це швидше, як це питання , але для JavaScript.


2
приклади a.toString (2), здається, не працюють на -1
барлоп

1
Також можливо перетворити з двійкового в десятковий: stackoverflow.com/questions/11103487/…
Anderson Green

І коли я сказав "у двійковій формі", це може бути трохи неоднозначно. Я маю на увазі внутрішнє представлення бітових рядків, яке є доповненням 2s, тому позитивні числа будуть в базі 2 і з провідним 0, (а від'ємні числа не записуються не символом мінус або з поданням величини знака, а як функція їх позитивного еквівалента)
барлоп

Відповіді:


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

dec2bin(1);    // 1
dec2bin(-1);   // 11111111111111111111111111111111
dec2bin(256);  // 100000000
dec2bin(-256); // 11111111111111111111111100000000

Можна використовувати Number.toString(2)функцію, але вона має деякі проблеми при поданні від'ємних чисел. Наприклад, (-1).toString(2)вихід є "-1".

Щоб виправити цю проблему, ви можете скористатися непідписаним правильним зсувом оператора зсуву ( >>>), щоб примусити свій номер до непідписаного цілого.

Якщо ви запустите, (-1 >>> 0).toString(2)ви змістите свій номер 0 біт вправо, що не змінює саме число, але воно буде представлено у вигляді непідписаного цілого числа. Код, наведений вище, виведе "11111111111111111111111111111111"правильно.

Це питання має додаткове пояснення.

-3 >>> 0 (правильний логічний зсув) примушує свої аргументи до непідписаних цілих чисел, ось чому ви отримуєте 32-бітове двоє доповнення подання -3.


7
Ось пояснення
fernandosavio

пройшов деякий час, оскільки я спробував javascript, але спробував його тут w3schools.com/js/tryit.asp?filename=tryjs_output_alert з цим <script> window.alert ((- 3 >>> 0) .toString (2)); </script> так, це спрацювало
барлоп

1
toString (2) не працює, оскільки ви отримуєте введення тексту. Використовуйте це: функція decToBase (dec, база) {return parseInt (dec) .toString (base); } сигнал (decToBase (dec, 2));
Маг

Ви припускаєте, що введенням є текст, але функція у відповіді очікує ціле число ... Отже, якщо введенням є текст, просто перетворіть його на ціле число, скористайтеся підробленим бітсифтом і це зроблено
fernandosavio

@Magus хто отримує введення тексту ?!
барлоп

207

Спробуйте

num.toString(2);

2 - це радіус і може бути будь-якою базою між 2 і 36

джерело тут

ОНОВЛЕННЯ:

Це буде працювати тільки для додатних чисел, Javascript представляє негативні двійкові цілі числа у позначенні двох доповнень. Я зробив цю маленьку функцію, яка повинна зробити трюк, я не перевірив її належним чином:

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 /programming/10936600/javascript-decimal-to-binary-64-bit 
        */
        return (~dec).toString(2);
    }
}

Я мав тут допомогу


не працює для -1. a = -1; document.write (Номер (a.toString (2))); показує -1
барлоп

Оновлення, як і раніше, не працює для негативних чисел ( -3повернень 1). Також я вважаю, що dec > 0має бути dec >= 0, що має принаймні виправити 0. Тому що dec2Bin(0)повертається 10.
Адам Мерріфілд

Обидва випадки в наведених вище коментарях дають правильний результат на моїй хромованій консолі - var a = -1; a.toString (2); "-1" var a = -3; a.toString (2); "-11"
Anmol Saraf

@AnmolSaraf Я бачу, що ви маєте на увазі, і в той час, коли люди говорять, що становить -5 у десятковій формі, а відповідь - -5 Якщо мова йде про від'ємні числа у двійковій формі, у певному сенсі, ви можете наклеїти знак мінус там, так 5 101 і -5 -101, але оскільки комп'ютери не зберігають мінус знаки, вони просто представляють 1s і 0s, тому, коли ми говоримо негативні числа у двійковій формі, ми дійсно маємо на увазі додавання від’ємного числа (знак мінус) в 1s і 0s. Деякі способи включають доповнення 1s, доповнення 2s та "знак та величину". Отже -101010101 або -0101010 - це не те, що люди мають на увазі під від’ємним числом у двійковій.
барлоп

Це посилання може зацікавити деякі stackoverflow.com/questions/12337360/… так чи інакше, ваша відповідь суперечить самій собі, ви пишете "Javascript представляє негативні двійкові цілі числа у позначенні двох доповнень". І ваш код говорить: "Тут ви можете представити число в 2 компліменті, але це не те, що JS використовує як [безглузду причину]" І ви також не даєте посилання.
барлоп

53

Бінарне слово "перетворити на бінарне" може означати три основні речі. Позиційна система числення, двійкове представлення в пам'яті або 32-бітові рядки. (про 64-бітні бітстринг див. відповідь Патріка Робертса )

1. Система числення

(123456).toString(2)перетворить числа в базову 2 позиційну систему числення . У цій системі від'ємні числа записуються із знаками мінус так само, як у десяткових.

2. Внутрішнє представництво

Внутрішнє представлення чисел - це 64-бітна плаваюча точка, і деякі обмеження обговорюються у цій відповіді . Немає простого способу створення представлення цього бітового рядка в JavaScript або доступу до конкретних бітів.

3. Маски та бітові оператори

MDN має хороший огляд того, як працюють бітові оператори. Важливо:

Побітові оператори трактують свої операнди як послідовність 32 біт (нулі та одиниці)

Перед застосуванням операцій 64-бітові числа з плаваючою точкою переносяться на 32-бітні цілі числа, підписані. Після їх перетворення назад.

Ось приклад коду MDN для перетворення чисел у 32-бітні рядки.

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"

Яка перевага використання цієї функції замість простого числа (число) .toString (2)?
Магз

5
@Magus Я думаю, що я пояснюю адекватно відмінності між числівниками та двійковими рядками. 32-бітний двійковий рядок завжди тридцять два символи, що складається з "1" s та "0" s. toString повертає фактичне число, представлене за допомогою систем позиційних чисел із заданою базою. Це залежить від того, чому ви хочете струни, вони мають дуже різні значення.
AnnanFay

вибачте, ви праві. Я стрибнув прямо до коду.
Маг

1
У вас виникли проблеми з провідними 0, використовуючи інші розміщені методи (конкретно на цьому номері 536870912, два провідні нулі видалено), але це рішення вирішило це правильно.
UberMouse

@UberMouse Так, >>> має провідне питання 0, я прийму це.
барлоп

43

Простий спосіб - це просто ...

Number(42).toString(2);

// "101010"

24
Я вважаю за краще(42).toString(2)
Віллем Д'Хассілер

33
Або ще коротше42..toString(2)
kapex

9
Люди борються з цим. Відповідь правильна, оскільки вона передає вхід (42) на ціле число, і цей рядок потрібен. Якщо ви отримаєте своє "число" з введення тексту, toString (2) не працюватиме.
Магз

4
@Kapep, чувак, це геніально. Звідки ви дізналися про це?
Pacerier

2
@BatuG. Синтаксис чисел дозволяє опустити частину після десяткового роздільника. Ви можете написати 1.те саме, що 1.0або просто 1(і так само ви можете опустити частину раніше і написати .5замість неї 0.5). Отже, у прикладі перша крапка - це десятковий роздільник, який є частиною числа, а друга точка - оператором крапки для виклику методу за цим числом. Вам потрібно використовувати дві крапки (або обернути число в круглих дужках), а не можна просто записати, 42.toString(2)оскільки аналізатор бачить крапку як десятковий роздільник та видаляє помилку через відсутність оператора крапок.
kapex

30

Ця відповідь намагається вирішити входи з абсолютним значенням у діапазоні 2147483648 10 (2 31 ) - 9007199254740991 10 (2 53 -1).


У JavaScript числа зберігаються у 64-розрядному поданні з плаваючою комою , але побітові операції примушують їх до 32-бітових цілих чисел у форматі комплементу двох , тому будь-який підхід, що використовує побітові операції, обмежує діапазон виводу до -2147483648 10 (-2 31 ) - 2147483647 10 (2 31 -1).

Однак якщо уникнути бітових операцій і зберегти 64-розрядне представлення з плаваючою точкою, використовуючи лише математичні операції, ми можемо надійно перетворити будь-яке безпечне ціле число в бінарне позначення доповнення 64-розрядних двох шляхом розширення знака 53-бітовим 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}

Для старих веб-переглядачів існують полізаповнення для таких функцій та значень:

Як додатковий бонус, ви можете підтримати будь-який радіус (2–36), якщо ви виконаєте перетворення комплементу для негативних чисел у цифрах ⌈64 / log 2 (radix) ⌉, використовуючи 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}

Якщо вас цікавить моя стара відповідь, яка використовувала знак ArrayBufferдля створення з'єднання між a Float64Arrayі a Uint16Array, будь ласка, зверніться до історії ревізії цієї відповіді .


Дякую, добре, що це працює на 64-бітній. Чи можете ви повідомити мені якісь переваги цієї відповіді над відповіддю Аннана?
барлоп

2
Набагато більший асортимент? Це працює на те, -(2**53)-1щоб 2**53-1замість того, -(2**31)щоб просто 2**31-1сподобатися відповіді Аннана.
Патрік Робертс

Так, це велика перевага, я розумію, що це зробить, хоча це і є трохи більше коду, але що я мав на увазі, мені цікаво, чи є якісь інші переваги?
барлоп

1
з 2 ** 32 + 1, останній (правий) біт очищається, коли його потрібно встановити.
Ловро

1
Працює, коли рядок: var exponent = ((uint16 [3] & 0x7FF0) >> 4) - 1023 + 1;
Ловро

15

Для 32-бітового рішення, з яким я б пішов, це код, який є кінцем цієї відповіді, який знаходиться на сайті developer.mozilla.org (MDN), але додано рядки для форматування A) і B) перевірка того, що кількість знаходиться в діапазоні.

Деякі запропонували x.toString(2) що не працює для негативів, він просто позначає знак мінус для них, що не є корисним.

Фернандо згадав про просте рішення (x>>>0).toString(2); яке добре підходить для негативів, але має незначне питання, коли х є позитивним. Він має вихід, починаючи з 1, що для додатних чисел не є правильним доповненням 2s.

Кожен, хто не розуміє факту додатних чисел, починаючи з 0, а від’ємних чисел з 1, в доповнення 2s, може перевірити цей SO QnA на 2s доповнення. Що таке "Доповнення 2"?

Рішення може включати в себе попереднє додавання 0 для позитивних чисел, що я зробив у попередньому перегляді цієї відповіді. І можна прийняти, що іноді має 33-бітове число, або можна переконатися, що число для перетворення знаходиться в межах - (2 ^ 31) <= x <2 ^ 31-1. Тож кількість завжди 32 біт. Але замість цього робити це рішення можна на mozilla.org

Відповідь і код Патріка довгий і, мабуть, працює для 64-розрядних версій, але у нього виявилася помилка, яку знайшов коментер, і коментатор виправив помилку Патріка, але Патрік у своєму коді має якесь "магічне число", яке він не коментував і має забули про Патріка і більше не розуміють власного коду / чому він працює.

Аннан мала деяку невірну та незрозумілу термінологію, але згадувала рішення developer.mozilla.org https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators Це працює для 32-бітних чисел.

Код досить компактний, функція складається з трьох рядків.

Але я додав регулярний вираз, щоб форматувати вихід у групах по 8 біт. Заснований на тому, як надрукувати число з комами як тисячні роздільники в JavaScript (я щойно доповнив його, згрупувавши його в 3s справа наліво та додавши коми , до групування в 8s справа наліво та додавання пробілів )

І, хоча mozilla зробила коментар щодо розміру nMask (число, яке вводиться), що це повинно бути в діапазоні, вони не перевіряли чи видавали помилку, коли число знаходиться поза діапазоном, тому я додав, що.

Я не впевнений, чому вони назвали свій параметр 'nMask', але я залишу це так, як є.

Довідка: 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"


8

Ви можете написати власну функцію, яка повертає масив бітів. Приклад, як перетворити число в біти

Дільник | Дивіденд | біт / залишок

2 | 9 | 1

2 | 4 | 0

2 | 2 | 0

~ | 1 | ~

Приклад верхнього рядка: 2 * 4 = 8, а залишок 1, так 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
}

Прочитайте залишки знизу вгору. Цифру 1 посередині вгорі.


1
Btw, чому ти Math.floor(number%2)замість цього number = Math.floor(number/2)?
Pacerier

1
Причина в тому, що число% 2 не дорівнює числу / 2. Нас цікавить залишок, а не коефіцієнт.
supritshah1289

0

Я використовував інший підхід, щоб придумати щось, що робить це. Я вирішив не використовувати цей код у своєму проекті, але подумав, що залишу його десь актуальним, якщо він комусь корисний.

  • Не використовує примус доповнення бітів або двох змін.
  • Ви вибираєте кількість бітів, що виходить (вона перевіряє дійсні значення "8", "16", "32", але я припускаю, що ви могли це змінити)
  • Ви вибираєте, чи буде це трактувати як ціле підписане чи неподписане число.
  • Він перевірить проблеми діапазону, враховуючи поєднання підписаних / неподписаних та кількості бітів, хоча ви хочете покращити обробку помилок.
  • Він також має "зворотну" версію функції, яка перетворює біти назад до int. Вам це знадобиться, оскільки, ймовірно, немає нічого іншого, що інтерпретуватиме цей вихід: 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("---");


-1

Ще одна альтернатива

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));

Будь ласка, дивіться відповідь Вінсента та коментар до нього, він стосуватиметься і вашої публікації
барлоп,

Це було написано у коментарі до його відповіді, не погоджуючись, та з деякою згодою інших: "Це може бути корисно для вивчення інформатики, щоб побачити, як це зробити вручну, щоб навчити себе, але це не те, що я прошу! Якщо ви збираєтесь винаходити колесо, роблячи це так вручну, тоді це повинно бути принаймні з перевагою підвищення ефективності або деякої переваги, як збільшення розміру значень, з якими він може впоратися. Я не бачу будь-яке обговорення від вас, де зазначається якась така перевага там ".
барлоп

Крім того, ваше рішення повністю не вдається, воно робить позитивні цифри починаючи з 1 і повністю не вдається для негативних чисел, а моє питання згадало позитивне чи негативне
барлоп

Тож ваша "відповідь" неправильна на багатьох багатьох рівнях. І завжди слід переглянути інші відповіді, перш ніж публікувати відповідь
барлоп,

-2

Це мій код:

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();

3
Це може бути корисно для вивчення інформатики, щоб побачити, як це робити вручну, щоб навчити себе, але це не те, що я прошу! Якщо ви збираєтесь винаходити колесо, роблячи це так вручну, тоді це повинно бути принаймні з перевагою підвищення ефективності або деякою перевагою, як збільшення розміру значень, з якими він може впоратися. Я не бачу жодної дискусії від вас, яка б зазначала там таку перевагу.
барлоп

-3

Це рішення. Це досить просто

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.
        */

1
Це рішення вже було запропоновано багато разів, і, як коментується ОП вже 30 березня 1212 о 9:01, воно не працює для негативних цифр.
Адріан Ш

@AdrianW Я пропоную скасувати це. Зауважую, ви цього не зробили. Що потрібно тоді, щоб ти спростував відповідь ?!
барлоп
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.