Avatar ·

Как преобразовать десятичное число в шестнадцатеричное в JavaScript?

Всем привет! Я новичок в JavaScript и столкнулся с проблемой при работе с числами. Мне нужно написать функцию, которая принимает десятичное число (например, 255 или 16) и возвращает его шестнадцатеричное представление в виде строки. Я знаю, что в CSS и HTML цвета часто задаются в hex-формате, например #FF0000, и хочу научиться получать такие значения программно. Я пробовал использовать метод `toString()`, но не уверен, что делаю это правильно. Вот мой код: ```javascript function decToHex(num) { return num.toString(16); } console.log(decToHex(255)); // Выводит "ff" ``` Это работает, но я хочу, чтобы результат всегда был в верхнем регистре (например, "FF" вместо "ff") и чтобы для чисел меньше 16 добавлялся ведущий ноль (например, "0A" для числа 10). Кроме того, мне нужно обрабатывать отрицательные числа? И как быть с дробными числами, например 3.14? Буду благодарен за подробное объяснение с примерами. Возможно, есть встроенные методы или более правильный подход, чем моя кустарная функция? Также интересует, как преобразовать обратно — из hex в десятичное число. Заранее спасибо за помощь! <<>>

Основное решение: метод toString(radix)

Самый простой и правильный способ преобразовать десятичное число в шестнадцатеричное — использовать встроенный метод Number.prototype.toString(radix). Параметр radix указывает основание системы счисления (от 2 до 36). Для hex передаём 16:

const decimal = 255;
const hex = decimal.toString(16); // "ff"
console.log(hex);

Форматирование: верхний регистр и ведущие нули

Чтобы получить hex в верхнем регистре, добавьте .toUpperCase(). Для чисел меньше 16 (однозначный hex) можно использовать .padStart(2, '0') для добавления ведущего нуля:

function decimalToHex(num) {
  // Преобразуем в hex, переводим в верхний регистр, 
  // добавляем ведущий ноль до длины 2 символа
  return num.toString(16).toUpperCase().padStart(2, '0');
}

console.log(decimalToHex(255)); // "FF"
console.log(decimalToHex(10));  // "0A"
console.log(decimalToHex(0));   // "00"

Обработка отрицательных чисел

Метод toString(16) для отрицательных чисел возвращает строку с минусом, например (-255).toString(16) даст "-ff". Если вам нужно беззнаковое представление (например, для цветов), используйте побитовый сдвиг >>> 0, который преобразует число в 32-битное беззнаковое целое:

function decimalToHexSigned(num) {
  // >>> 0 преобразует в беззнаковое 32-битное целое
  return (num >>> 0).toString(16).toUpperCase().padStart(8, '0');
}

console.log(decimalToHexSigned(-1));   // "FFFFFFFF"
console.log(decimalToHexSigned(255));  // "000000FF"
console.log(decimalToHexSigned(-255)); // "FFFFFF01"

Дробные числа

Для дробных чисел (например, 3.14) toString(16) работает, но выдаёт дробную часть в hex-формате, что редко бывает нужно. Обычно дробные числа сначала округляют до целого:

function decimalToHexFromFloat(num) {
  // Округляем до целого и преобразуем
  return Math.round(num).toString(16).toUpperCase();
}

console.log(decimalToHexFromFloat(3.14)); // "3"
console.log(decimalToHexFromFloat(255.7)); // "100"

Обратное преобразование: hex → десятичное

Для преобразования hex-строки в число используйте parseInt(hexString, 16) (регистр не важен):

const hexColor = "FF";
const decimal = parseInt(hexColor, 16); // 255
console.log(decimal);

// Для строк с решёткой (#FF0000) удалите #
const hexWithHash = "#FF0000";
const rgb = parseInt(hexWithHash.slice(1), 16); // 16711680
console.log(rgb);

Универсальная функция

Соберём всё вместе в одну удобную функцию:

function toHex(num, options = {}) {
  const {
    upperCase = true,
    padLength = 2,
    unsigned = false
  } = options;

  let value = unsigned ? (num >>> 0) : num;
  let hex = value.toString(16);

  if (upperCase) hex = hex.toUpperCase();
  if (padLength) hex = hex.padStart(padLength, '0');

  return hex;
}

// Примеры использования:
console.log(toHex(255));                 // "FF"
console.log(toHex(10, { padLength: 4 })); // "000A"
console.log(toHex(-1, { unsigned: true })); // "FFFFFFFF"
console.log(toHex(255, { upperCase: false })); // "ff"

Этот подход гибкий, покрывает все основные случаи и легко расширяется. Для большинства задач достаточно простого num.toString(16).toUpperCase().

<<>>

Альтернативный подход: ручная реализация алгоритма

Если вы хотите понять, как работает преобразование "под капотом", можно написать свою функцию. Алгоритм основан на делении числа на 16 и сборе остатков:

function decimalToHexManual(num) {
  if (num === 0) return "0";
  
  const digits = "0123456789ABCDEF";
  let result = "";
  let n = Math.abs(num); // работаем с модулем числа
  const isNegative = num < 0;

  while (n > 0) {
    result = digits[n % 16] + result;
    n = Math.floor(n / 16);
  }

  return (isNegative ? "-" : "") + result;
}

console.log(decimalToHexManual(255)); // "FF"
console.log(decimalToHexManual(10));  // "A"
console.log(decimalToHexManual(-255)); // "-FF"

Когда это может пригодиться?

  • В учебных целях — чтобы понять суть перевода между системами счисления.
  • В средах, где toString(16) недоступен (например, очень старые браузеры или ограниченные окружения).
  • Для кастомных систем счисления (например, base 20 или base 32).

Однако для продакшена всегда используйте встроенный метод — он быстрее, надёжнее и короче. Ручная реализация полезна только для обучения или специфических задач.