- Преобразовать число в двоичное в Java
- 1. Использование встроенных методов
- 2. Наивное решение
- Saved searches
- Use saved searches to filter your results more quickly
- PervuhinRoman/JavaNumeralConverter
- Name already in use
- Sign In Required
- Launching GitHub Desktop
- Launching GitHub Desktop
- Launching Xcode
- Launching Visual Studio Code
- Latest commit
- Git stats
- Files
- README.md
- About
- Преобразуем строки в числа в разных системах счисления
- Исходная задача
- Пишем код
- Заключение
Преобразовать число в двоичное в Java
В этом посте мы обсудим, как преобразовать число в двоичное в Java.
1. Использование встроенных методов
Стандартным решением для преобразования числа в двоичное в Java является использование Integer.toBinaryString() метод, который возвращает двоичное представление указанного целого числа в строковом формате.
результат:
1001011
Точно так же вы можете преобразовать длинное значение, используя Long.toBinaryString() метод.
результат:
1001011
В качестве альтернативы вы можете использовать toString(i, r) метод, который возвращает строковое представление i в основе r . Однако это не работает так, как предполагалось для отрицательных чисел.
результат:
1001011
Если вам нужно, чтобы двоичное представление целого числа было дополнено нулями слева, вы можете использовать любой из методов, описанных в это почта:
2. Наивное решение
Мы даже можем написать собственную процедуру для преобразования числа в двоичный формат, как показано ниже:
результат:
00000000000000000000000001001011
Вот рекурсивная версия приведенного выше кода:
результат:
00000000000000000000000001001011
Вот и все о преобразовании числа в двоичное в Java.
Средний рейтинг 4.5 /5. Подсчет голосов: 8
Голосов пока нет! Будьте первым, кто оценит этот пост.
Сожалеем, что этот пост не оказался для вас полезным!
Расскажите, как мы можем улучшить этот пост?
Спасибо за чтение.
Пожалуйста, используйте наш онлайн-компилятор размещать код в комментариях, используя C, C++, Java, Python, JavaScript, C#, PHP и многие другие популярные языки программирования.
Как мы? Порекомендуйте нас своим друзьям и помогите нам расти. Удачного кодирования 🙂
Этот веб-сайт использует файлы cookie. Используя этот сайт, вы соглашаетесь с использованием файлов cookie, нашей политикой, условиями авторского права и другими условиями. Читайте наши Политика конфиденциальности. Понятно
Saved searches
Use saved searches to filter your results more quickly
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.
JavaNumeralConverter — конвертер систем счисления, способный переводить как целые, так и дробные числа в системы счисления от 2-ой до 36-ти ричной 💻
PervuhinRoman/JavaNumeralConverter
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Sign In Required
Please sign in to use Codespaces.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching Xcode
If nothing happens, download Xcode and try again.
Launching Visual Studio Code
Your codespace will open once ready.
There was a problem preparing your codespace, please try again.
Latest commit
Git stats
Files
Failed to load latest commit information.
README.md
JavaNumeralConverter — конвертер систем счисления, способный переводить как целые, так и дробные числа в системы счисления от 2-ой до 36-ти ричной 💻
- Знать что такое система счисления и как строить системы счисления
- Понимать «бумажный» алгоритм перевода (конвертации) чисел между СС
- Знать что такое таблица ascii
- Понимать как связаны между собой типы данных int и char
- Алгоритм содержит методы:
- InputCheck(String number, int base, int newBase) для проверки пользовательского ввода на корректность
- AsciiFuncToNumbers(char item) для преобразования символа согласно таблице ascii в числовое значение, необходимое для расчётов
- AsciiFuncToSymbols(int item) для преобразования числа в символ для приведения к заданной системе счисления
- ToDec(String number, int base) для преобразования числа в десятичную систему счисления
- FromDecToNewBase(double decNumber, int newBase) для преобразования числа в заданную систему счисления
- main основной метод
About
JavaNumeralConverter — конвертер систем счисления, способный переводить как целые, так и дробные числа в системы счисления от 2-ой до 36-ти ричной 💻
Преобразуем строки в числа в разных системах счисления
Одной из частых рутин на работе является преобразование и извлечение чисел из строк текста. Самый наивный и простой подход в языке Java при преобразовании строки в число, это использовать Double.parseDouble(String num) . Проблема этого метода в том, что он имеет баги в различных SDK, например в Android. Кроме того, данному методу не передаётся информация об основании системы счисления. Можно, конечно, использовать классы оболочки, передавая им в конструктор основание системы, но хотелось бы извлекать данную информацию из самой строки автоматически.
Исходная задача
Дана произвольная строка. Выяснить, составляет ли она какое-либо (действительное) число в определённых системах счисления. Вычислить знак числа. Выделить в строке мантиссу и экспоненту, обработать их отдельно, и перемножить друг на друга. Для простоты рассмотрим четыре системы счисления: десятичную, двоичную, восьмеричную и шестнадцатиричную.
Для каждой системы счисления, кроме десятичной определим соответствующий префикс:
У числа может быть задана экспонента. Определим три вида экспоненты, имеющие следующие префиксы:
- ‘H’ | ‘h’ : десятичная экспонента для 16-ричных чисел, поскольку буква E уже занята (является цифрой 14 в данной системе).
- ‘E’ | ‘e’ : десятичная экспонента для остальных чисел, чьё основание системы ниже 14.
- ‘P’ | ‘p’ : двоичная экспонента для всех представленных чисел.
Пишем код
Так напишем же простой метод для преобразования строки в число из соответствующей системы счисления (указанной в строке) в десятичную. Данный метод должен корректно отделять целую часть от той, что следует после запятой (точки). Обработка знака и экспоненты будет дана ниже.
public class ProcessNumber < private static final String digits = "0123456789ABCDEF"; /* Преобразует строку num в десятичное число типа double из указанного основания base Может вызвать переполнение (выход за пределы диапазона целых чисел)! */ private static double parseNumber(String num, int base)< num = num.toUpperCase(); // digits are in UPPER_CASE double val = 0; int i = 0; while(i < num.length()) // пока не кончилась строка < char c = num.charAt(i); if(c == '.') < // нашли точку '.' i++; // Переместить на следующий символ и выйти из цикла. break; >int d = digits.indexOf(c); // Индексы совпадают с числами из [0..15] if(d == -1 || d >= base) return Double.NaN; val = base * val + d; i++; > int power = 1; // вычислить лишний порядок. while(i < num.length()) < char c = num.charAt(i); int d = digits.indexOf(c); if(d == -1 || d >= base) return Double.NaN; power *= base; // увеличиваем степень порядка на единицу val = base * val + d; i++; > return val / power; > >
Сейчас метод parseNumber() выполняет ровно одну задачу. Он пытается преобразовать строку num в число типа double, начиная с указанного основания base. Если обнаружен недопустимый символ в строке num, то метод вернёт специальную константу класса Double не-число (NaN — Not a Number).
Самому методу нужно передавать строку без экспоненты, знака, и префикса основания системы счисления. Их предстоит вычислить заранее. Если есть знак минус ( ‘-‘ ) то число просто умножается на минус единицу ( -1 ). Если есть экспонента, то число дополнительно умножается на неё. Прежде чем приступить к их вычислению, допустим, что нам уже известны данные компоненты. Напишем метод, который делает выбор на основе полученной информации, и выполняет соответствующее умножение преобразованного числа из заданного основания на полученную экспоненту и минус единицу, если необходимо.
public class ProcessNumber < // . parseNumber(String str, int base) < . >/* num - Число e - экспонента et - тип экспоненты base - основание системы счисления sign - знак числа (num > 0 => positive, num < 0 =>negative). esign - знак экспоненты. */ public static double parse(String num, String e, char et, int base, int sign, int esign) < if(num == null || num.length() == 0 || base < 1) // null значения =>NaN. return Double.NaN; double exp = 1; // Экспонента // Двоичная экспонента (по основанию 2) if((et == 'P' || et == 'p') && e != null && e.length() > 0) exp = Math.pow(2.0, parseNumber(e, 10)); // Десятичная экспонента (по основанию 10) else if( (et == 'E' || et == 'e' || et == 'H' || et == 'h') && e != null && e.length() > 0) exp = Math.pow(10.0, parseNumber(e, 10)); //e == null or e.length() == 0. // Указан тип экспоненты, но сама она отсутствует else if(et == 'E' || et == 'e' || et == 'H' || et == 'h' || et == 'P' || et == 'p') < return Double.NaN; >else // et is not [PpEeHh] => ignore exponent (exp == 1) (Нет экспоненты) exp = 1; if(esign < 0) exp = 1 / exp; double result = parseNumber(num, base); // Преобразовать численную часть. result = (result == Double.NaN) ? result : result * exp; if(sign < 0) result = 0 - result; //make number negative (include minus sign) return result; >>
Методу parse() уже передаются вычисленные компоненты числа, а именно: само число num, его экспонента e, основание экспоненты et, основание системы самого числа base и знак числа sign. В данном методе уже предусмотрена защита от противоречивых данных (например, когда экспонента равна null, но указан её тип, или когда основание системы счисления не является натуральным числом (меньше единицы)). В простом случае, если строка равна null, то данный метод вернёт не-число (NaN). Метод выполняет простую задачу, он просто вычисляет множители итогового выражения result, и выполняет умножение преобразованных строк (экспоненты и самого числа без неё) на переменную знака sign. А вызываемый метод processNumber() переводит строку компонента в число.
Теперь остаётся написать последний метод, который вычисляет знак, экспоненту и основание системы. Ниже дан его код.
public class ProcessNumber < . // parseNumber(String num, int base) < . >// parse(String num, String exp, char etype, int base, int sign) < . >/* В отличие от parseNumber(String num, int base) автоматически вычисляет основание base, экспоненту e, и её тип, а также знак числа sign. В случае успешного вычисления, передаёт вычисленные элементы методу parse(), который делает выбор (условный переход) множителей и преобразование строковых компонент уже через parseNumber(num, base). */ public static double parseNumber(String str) < if(str == null || str.length() == 0) //null is NaN. return Double.NaN; int sign = 1; // знак числа. int esign = 1; // знак экспоненты. int base = 10; // по умолчанию основание равно 10. int i = 0; if(str.charAt(0) == '-') < // Минус ->sign < 0. sign = -1; i = 1; // перейти к следующему знаку. >if(i > 0 && i == str.length()) //str is '-' (строка состоит только из '-') return Double.NaN; // suffix '0x' => 16 (hex) if(str.charAt(i) == '0' && (i + 1 != str.length()) && str.charAt(i + 1) == 'x') < base = 16; i += 2; >//suffix '0b' => 2 (binary) else if(str.charAt(i) == '0' && (i + 1 != str.length()) && str.charAt(i + 1) == 'b') < base = 2; i += 2; >//suffix '0c' => 8 (octal) else if(str.charAt(i) == '0' && (i + 1 != str.length()) && str.charAt(i + 1) == 'c') < base = 8; i += 2; >if(i == str.length())// строки вида (-0x -0b -0c 0x 0b 0c) return Double.NaN; //Вычислить экспоненту. int idx = str.indexOf('H'); idx = (idx == -1) ? str.indexOf('h') : idx; idx = (idx == -1) ? str.indexOf('P') : idx; idx = (idx == -1) ? str.indexOf('p') : idx; idx = (idx == -1 && base != 16) ? str.indexOf('E') : idx; idx = (idx == -1 && base != 16) ? str.indexOf('e') : idx; char etype = (idx == -1) ? 'N' : str.charAt(idx); //Когда нет экспоненты (idx + 1) == 0. if(idx + 1 == str.length())// no more digits after exponent letter ('12E' or 'FFP') return Double.NaN; String exp = null; //Отрицательная экспонента, но нет цифр 'E-' or 'P-' or 'h-' if(str.charAt(idx + 1) == '-' && idx != -1 && idx + 2 == str.length()) return Double.NaN; //Отрицательная экспонента. 'E-2' or 'p-10' if(str.charAt(idx + 1) == '-' && idx != -1) < exp = str.substring(idx + 2); esign = -1; >else exp = str.substring(idx + 1); //Положительная экспонента (после idx следует цифра) idx = (idx == -1) ? str.length() : idx; //if no exponent then idx >
Данный метод начинает со стандартной проверки на null-значения. Далее, если строка не null и имеет символы, то проверяется её самый первый символ. Если он имеет знак минуса ( ‘-‘ ) то множитель sign становится равен (-1). Иначе он остаётся равен 1. После вычисления знака идёт вычисление основания системы счисления по префиксу строки. После обработки префикса, снова проверяется наличие оставшейся части символов в строке. Если больше символов нет, то опять возвращается не-число (NaN). Если префикс основания отсутствует, то основание base считается равным 10. Затем вычисляется экспонента exp числа и индекс idx её начала для её последующего отделения от исходной строки. После вычисления всех компонентов, управление передаётся методу parse().
Заключение
Метод достаточно хорош, но ещё не идеален. При выходе из диапазона значений стандартных типов, можно получить неверный результат (а именно, отрицательные числа, когда как строка представляет положительное число, и наоборот). Он минует исключение NumberFormatException, возвращая не-число NaN когда обнаруживает недопустимый символ (не принадлежащий диапазону цифр в основании) а также NullPointerException, так как есть проверки на null (сводящиеся к замене null на NaN).
Следует также отметить, что самая последняя процедура processNumber(String num) имеет место уже с готовой лексемой num, лишённой лишних пробельных символов. При дублировании знака числа (минуса), результат будет снова NaN. Также, если сама экспонента NaN то и итоговое значение будет NaN. Однако процедура допускает наличие лидирующих нулей вначале числа.
Данную утилиту можно использовать только уже с коллекцией строк (цепочек), заранее выделенных из входного потока.