Преобразование числа в строку и обратно - PullRequest
0 голосов
/ 23 августа 2010

Я всегда использовал streams, printf, string (x) или любой другой язык, который предлагался для преобразования числовых типов в строку или обратно. Однако я никогда не задумывался над тем, как это на самом деле делается. Я искал в Google, но все результаты сводятся к тому, чтобы использовать эти разные методы, а не то, как на самом деле выполняется конверсия: (

Для целых чисел, использующих двоичные, восьмеричные и шестнадцатеричные, кажется довольно простым, поскольку каждая «цифра» в строке представляет собой заданную группу битов (например, для 2 шестнадцатеричных цифр, которые я знаю, это xxxxyyyy), поэтому я мог бы сделать это с помощью битовых сдвигов и принимая одну цифру за раз, например, для шестнадцатеричной строки 0xFA20 значение равно «(15 << 12) | (10 << 8) | (2 << 4) | (0 << 0)». </p>

Десятичные целые числа сложнее, поскольку основание 10 не отображается на основание 2 таким образом, и поэтому один бит может влиять на более чем одну десятичную цифру, делая преобразование в обоих направлениях более сложным ...

Что касается чисел с плавающей запятой, я действительно понятия не имею. Я думаю, что целые и дробные части можно рассматривать отдельно или что-то? Как насчет экспоненты, набора значащих цифр или набора десятичных знаков?

Ответы [ 3 ]

1 голос
/ 23 августа 2010

Десятичные преобразования немного медленнее, но на самом деле не намного сложнее. Давайте посмотрим на шестнадцатеричное преобразование немного более похоже на то, что мы, вероятно, написали бы его в реальном коде. Например, в C ++ вы можете выполнить преобразование примерно так:

char digits[] = "0123456789abcdef";
std::string result;

int input = 0xFA20;

while (input) {
    int digit = input & 0xf; // or: digit = input % 0xf;
    input >>= 4;             // or: input /= 16;
    result.push_front(digits[digit]);
}

Однако сейчас у него есть магические числа. Давайте избавимся от них:

const int base = 16;

while (input) { 
    int digit = input % (base - 1);
    input /= base;
    result.push_front(digits[digit]);
}

В процессе избавления от этих магических чисел мы также сделали подпрограмму почти универсальной - если мы изменим значение «base», остальная часть подпрограммы все еще будет работать и преобразует входные данные в указанный база. По сути, единственное другое изменение, которое нам нужно сделать, - это добавить больше в массив «цифры», если мы хотим поддерживать базы больше 16.

Это также игнорирует несколько вещей для простоты. Очевидно, что если число отрицательное, вы обычно устанавливаете флаг, конвертируете в положительное число и, в конце, если флаг был установлен, вставляете «-» в строку). С дополнением 2 есть угловой регистр для максимально отрицательного числа, которое не может быть преобразовано в положительное число (без преобразования в тип с большим диапазоном). Обычно вы справляетесь с этим, продвигая большинство типов. Для вашего наибольшего целочисленного типа (который вы не можете рекламировать) обычно проще всего жестко закодировать это одно значение.

В принципе, числа с плавающей точкой не сильно отличаются - вы все равно в основном делаете математические манипуляции для генерации одной цифры за раз. Фактически, это становится более сложным просто потому, что вам обычно приходится иметь дело с парой различных форматов (по крайней мере, «базовая» с плавающей запятой и своего рода «научным» форматом), а также с переменными ширины и точности поля. К тому времени, когда вы разберетесь с этим, у вас будет несколько сотен строк кода или около того - не слишком возмутительно, но, возможно, немного больше, чем имеет смысл включать сюда.

1 голос
/ 23 августа 2010

Я искал в Google, но все результаты сводятся к тому, чтобы использовать эти разные методы, а не то, как на самом деле выполняется конверсия: (

По соображениям производительности преобразование из одного представления в другое (особенно преобразования с плавающей запятой / целочисленные) часто является низкоуровневой инструкцией ЦП и реализуется на уровне процессора. Вот почему вы, как правило, не видите его повторно реализованным в библиотеках или на уровне языка.

Это особенно распространено в мире обработки сигналов, например, где вы хотите взять сигнал и преобразовать его в дискретное целочисленное значение в некотором диапазоне.

0 голосов
/ 23 августа 2010

Для целых чисел вы можете найти остаток от деления, это последняя цифра, разделить на 10, найденный модульный остаток - это одна последняя цифра, и так далее.Числа с плавающей запятой состоят из двух частей - значащих цифр и показателя степени, то есть число = значимые цифры * (база ^ экспонента), где основание может быть 10, 2 или другое число.

...