2009-08-13 6 views
0

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

Convert Hex to Decimal when no datatype can hold the full number

На этот раз, это обратное. У меня есть число (в удобной строке с нулевым завершением), и мне нужны байты, которые делают этот номер. Тем не менее, я работаю в 32-битной архитектуре для микроконтроллера, поэтому у меня нет возможности использовать atoi, так как число больше 32 бит.

Есть ли у кого-нибудь идея о том, как отменить алгоритм, предусмотренный в первой ссылке, чтобы вернуть исходный результат? Мои способности по модулю арифметики не позволяют мне.

Быстрый пример: 155.207.231.135 к 0x [24] [23] [12] [66] [9F] (скобки отдельные байты)

ответ

1

Вы можете сделать что-то похожее на разделение BigInt.

a = atoi of lower 7 decimal digits 
b = atoi of remaining upper decimal digits 


for (int i = 0; i < 5; i++) 
{ 
    a += 10000000 * (b % 256); 
    b /= 256; 
    Result[i] = a % 256; 
    a /= 256; 
} 
+1

Я не понимаю, почему a% 32, когда массив байтов может удерживать до% 256 –

+0

. Вы правы, у меня, по-видимому, не было достаточного количества кофеина, когда я писал, исправлено :) – matthock

+0

Хотя подумайте об этом, который начинает представлять проблему с переполнением. Необходимо ограничить это до 7 десятичных цифр, чтобы этого избежать. – matthock

0

Вам нужно ассемблер для этого , Псевдокод:

int low = 0 // lower 32 bit 
int high = 0 // higher 32 bit 

for (int i=0; i<string.length(); i++) { 
    int digit = string.get(i) - '0'; 
    int a = low; 
    int b = high; 
    a <<= 1; b += overflow;    // *2 
    a <<= 1; b += overflow;    // *4 
    a += low; b += overflow; b += high; // *5 
    a <<= 1; b += overflow;    // *10 
    a += digit; b += overflow;   // +digit 
    low = a; high = b; 
} 

Таким образом, вы создаете 64-битный регистр, используя два 32-битных ints. Для каждого цикла, то:

value *= 10 + digit; 

После этого вам нужно только, чтобы пропустить 0 байт в начале результирующего значения, чтобы получить байты, которые вы ищете.

+0

Я не понимаю, что такое «переполнение». –

+0

Каждый процессор имеет бит переполнения или переноса, который устанавливается, когда последняя операция не вписывалась в задействованные типы данных. Если у вас есть байт со значением 0xff, и вы сдвигаете его вправо один раз, бит переноса будет установлен (так как был установлен самый верхний бит), а байт будет 0xfe. –

+0

Часто у вас есть «ADDC» (добавить с переносом), чтобы вы могли «ROR a; AADC# 0, b;» или есть ветвь: «ROR a; BCC#label; ADD # 1, b; #label», поэтому ADD пропускается, если бит переноса не установлен. –

0

Просто проанализируйте строку слева направо, умножив предыдущий результат на десять и добавив цифру.

Вот код на C#, чтобы показать концепцию. Первые два метода в математике на массив:

static void Mul(byte[] data, int num) { 
    int n = 0; 
    for (int i = data.Length - 1; i >= 0; i--) { 
     n += (int)data[i] * num; 
     data[i] = (byte)n; 
     n >>= 8; 
    } 
} 

static void Add(byte[] data, int num) { 
    for (int i = data.Length - 1; num > 0; i--) { 
     num += (int)data[i]; 
     data[i] = (byte)num; 
     num >>= 8; 
    } 
} 

Тогда вы просто сделать:

string s = "155207231135"; 
byte[] result = new byte[16]; 
foreach (char c in s) { 
    Mul(result, 10); 
    Add(result, c - '0'); 
} 

В результате в массиве result, проложенный с нулевыми байтами слева.

Не должно быть трудно перевести на C ... :)