Шестнадцатеричное число к Десятичному преобразованию [осуществление K&R]

Как отметил @Jon Skeet, использование java.time - хорошая идея. Используйте Date.toInstant и конвертируйте в LocalDateTime по вашему смещению:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Date;
import java.util.Locale;

public class SO201904030814 {

    public SO201904030814() {
    }

    public static void main(String[] args) throws ParseException {
        SimpleDateFormat sdf3 = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ENGLISH);

        Date d1 = sdf3.parse(String.valueOf("Mon Mar 04 12:19:50 GMT+05:30 2019"));

        LocalDateTime dateTime = LocalDateTime.ofInstant(d1.toInstant(), ZoneOffset.of("+05:30"));

        System.out.println("check..." + d1 + " vs " + dateTime);

    }

}

HTH!

6
задан Deduplicator 23 January 2015 в 11:19
поделиться

8 ответов

Processing the string from left to right is simpler and arguably more readable for those comfortable with math. The strategy is realizing that, for example, 1234 = (((1 x 10) + 2) x 10 + 3) x 10 + 4

In other words, as you process each digit from left to right, multiply the previous total by the base, effectively "moving it left" one position, then add the new digit.

long decFromHexStr(const char *hexStr)
{
    int i;
    long decResult = 0;  // Decimal result

    for (i=0;  i < strlen(hexStr);  ++i)
    {
        decResult = 16 * decResult + decFromHexChar(hexStr[i]);
    }
    return decResult;
}

Experienced programmers would probably use a pointer to step through the string instead of treating it as an array:

long decFromHexStr(const char *pHex)
{
    long decResult = 0;

    while (*pHex != '\0')
    {
        decResult = 16 * decResult + decFromHexChar(*pHex++);
    }
    return decResult;
}

Since you're learning, it's worth studying the coding style and deciding whether you find it helpful or not, so you'll build good habits early.

Have fun!

4
ответ дан 8 December 2019 в 04:55
поделиться

Основная идея Митча правильна, но давайте рассмотрим ее немного подробнее.

Шестнадцатеричное число - это просто основание 16, что означает, что цифры (справа налево) имеют значения в виде

цифр × 16 0 (т. е. 1)
цифра × 16 1 (т. е. 16)
цифра × 16 2 (256)

и т. д. Так, например, 0xE равно 14.

Вам понадобится цикл, начинающийся с правого конца строки . Допустим, строка s, длина (s) - длина строки. В псевдокоде вы хотите, чтобы

value = 0
r = 1   // ask yourself "what values does r take as this proceeds?"
for i from length(s)-1 to 0   // Ask yourself "why length(s)-1?"
   value = value + (digitval(s[i])*r)
   // get ready for the next digit
   r = r * 16

digitval (char c) должна была быть функцией, которая переводит checract в «0123456789ABCDEF» в значения между 0 и 15 (включительно). Я оставлю это как упражнение, с одна подсказка: «массивы».

будьте осторожны с одной дополнительной проблемой; поскольку у вас может быть начальный «0» или «0x», вам необходимо убедиться, что вы обрабатываете эти случаи.

5
ответ дан 8 December 2019 в 04:55
поделиться

Я, вероятно, не делаю большой вклад, выше есть хорошие ответы. Но я попробую.

Как и другие до меня, я оставляю вам некоторые функции для реализации.

int htoi(const char* x)
{

        unsigned int current_position;/*current position is to be defined*/
        int prefixed=0;                                                         
        int dec=0;
        char* y = x;

        if (x && x+1 && (*(x+1)=='x' || *(x+1)=='X')){  /*Is 0x or 0X prefix present?*/
                prefixed= PREFIXED;             
        }

        if (prefixed) y+=2; /*Jumps over 0x or 0X*/     


        while (*y){
                /*getPos(const char*) and singleHexToDec(const char*,unsigned int) functions to be implemented*/
                current_position=getPos(y);
                dec+=singleHexToDec(y,current_position); 
        }
        return dec;
}
1
ответ дан 8 December 2019 в 04:55
поделиться

Рекурсия не требуется. Вам просто нужно выполнить цикл назад по строке (т. Е. Начиная с столбца единиц), суммируя однозначное число, умноженное на его множитель положения радиуса. Это псевдокод, который не обрабатывает необязательный префикс 0x (и не проверяет возможность переполнения):

long total = 0;
long multiplier = 1;
for (int i = string.length - 1; i >= 0 i--)
{
   digit = ConvertSingleHexDigittoInt(string[i]);
   total += digit * multiplier;
   multiplier *= 16;
}

Я оставил вам простую реализацию ConvertSingleHexDigittoInt ():)

12
ответ дан 8 December 2019 в 04:55
поделиться

try to explain with my rude english :(

My code (assume that all inputs are corrects. Avoid defensive programing)

#include <stdio.h>


enum { SZ = 11 };

unsigned int htoi(const char *s);


int main()
{

  char buff[SZ];  //Max 11 char: 0x XX XX XX XX '\0' (2 + 8 + 1)

  while(fscanf(stdin, "%s", buff) != EOF)
    printf("%X\n", htoi(buff) ); 

  return 0;
}


unsigned int htoi(const char *s)
{
  unsigned int i, r = 0;

  for(i = (s[1] == 'x') ? 2 : 0; s[i] != '\0'; i++)
    r = ( r << 4 ) +  ( (s[i] > '9') ? 0x9 : 0x0 ) + ( s[i] & 0xF );

  return r;
}

Ok, first of all, assign r = 0. Then, when we start for-bucle, we give an init value to index variable i. We have to check if string has 0x format or not. We only need to check position 1 to know if we are treating an input string with 0x format or without it.

Now, we have an index pointing to first correct character! For each iteraion we displace 4 bits to the left. We gain 4 zeros. A perfect gap to add a new hex digit! Example:

Input: 0xBE1234

Is s[1] == 'x' ? true then i = 2;
r = 0;

iter 1: r = 0x0; r = 0x0; r = 0xB;
iter 2: r = 0xB; r = 0xB0; r = 0xBE;
iter 3: r = 0xBE; r = 0xBE0; r = 0xBE1;
iter 4: r = 0xBE1; r = 0xBE10; r = 0xBE12;
iter 5: r = 0xBE12; r = 0xBE120; r = 0xBE123;
iter 6: r = 0xBE123; r = 0xBE1230; r = 0xBE1234

May be this is a bit complicate:

 r = ( r << 4 ) + ( (s[i] > '9') ? 0x9 : 0x0 ) + ( s[i] & 0xF );

First of all, we displace 4 bits, same as multiplication per 16 but more efficient. Then, we look if we have an ASCII character bigger than '9'. If it's true, we are working with A, B, C, D, E, F or a, b, c, d, e, f. Remember, we assume that we have a correct input. Ok, now take a look to ASCII table:

A = 0100 0001  -  a = 0110 0001
...
F = 0100 0110  -  f = 0110 0110

but we want something like this:

A = 0000 1010  -  a = 0000 1010
...
F = 0000 1111  -  f = 0000 1111

How we do it? After displacement, we clear 4 most significant bit with mask s[i] & 0xF:

s[2] == 'B' == 0100 0010
s[2] & 0xF == 0000 0010

and add 9 for adapt to an integer value ( only in case that s[i] in { 'A'...'F', 'a' ... 'f' } )

s[2] & 0xF + 0x9 = 0000 0010 + 0000 1001 = 0000 1011 (0xB)

Finally, we add to displaced r value and assign to r. Execution sequence for second iteration (s[3]):

r == 0xB, s[3] == 'E' == 0100 0101 (start iter 2)
(r << 4) == 0xB0, s[3] == 'E' == 0100 0101 (displacement r << 4 )
(r << 4) == 0xB0, (s[3] & 0xF + 0x9) == 0000 1110 == 0xE (clear most significant bits of s[3] and add 0x9)
r = (r << 4) + ( s[3] & 0xF + 0x9 ) == 0xBE == 1011 1110 (add all and assign to r)

What's happen if we have a number character like s[4]?

s[4] == '1' == 0011 0001
s[4] & 0xF == 0000 0001

Displacement r four positions, add 0 (nothing), add result of logic operation s[i] & 0xF and finally, assign to r.

r == 0xBE, s[4] == '1' == 0011 0001 (start iter 3)
(r << 4) == 0xBE0, s[4] == '1' == 0011 0001 (displacement r << 4 )
(r << 4) == 0xBE0, (s[4] & 0xF + 0x0) == 0000 0001 (clear most significant bits of s[4] and add 0)
r = (r << 4) + s[4] & 0xF == 0xBE1 == 1011 1110 0001 (add all and assign)

Remember, we shift 4 so we don't mesh digit bits because we are adding less significant bits with a gap of four zeros.

PD: I promise improve my english for explain better, sorry.

1
ответ дан 8 December 2019 в 04:55
поделиться

Что на самом деле означает шестнадцатеричное число? Давайте возьмем 15FA . Это означает

1 * 16^3 + 5 * 16^2 + 15 * 16^1 + 10 * 16^0

. Обратите внимание, что A представляет десять, B одиннадцать и так далее до F , что представляет пятнадцать. Также 16 ^ 0 равно 1.

Итак, все, что нам нужно сделать, это вычислить значение вышеприведенного выражения! Самый простой способ, вероятно, состоит в том, чтобы сделать это в следующем порядке:

10 * 1
15 * 16
5  * 256   //256  = 16 * 16
1  * 4096  //4096 = 16 * 16 * 16

Это может продолжаться, если есть еще цифры. Все, что вам действительно нужно, это цикл и несколько переменных.

Существует еще один метод, который объясняется разложением приведенного выше выражения следующим образом:

((1 * 16 + 5) * 16 + 15) * 16 + 10

Если хотите, попробуйте каждый из этих методов.

Более продвинутый информация:

В основном компьютеры используют базу 2 (также называемую бинарной) для всех своих чисел и расчетов. Даже строка «1A6DC0» кодируется 1 и 0, которые в конечном итоге отображаются на экране в виде букв и цифр.

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

Например, когда вы делаете

x = (11 + y) * 6;

вы не ' Не нужно беспокоиться , что 11 и 6 будут представлены как серии высокого и низкого напряжения на некоторой стадии. Это просто работает, как вы ожидаете. Преобразование между десятичной (используемой нами системой счисления) в двоичную и обратно - это простой процесс, который компьютеры могут легко выполнить, и поэтому они делают это для нас автоматически, чтобы упростить нашу работу.

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

Например, 15FA будет расширяться как this:

1 -> 0001
5 -> 0101
F -> 1111
A -> 1010
15FA -> 0001 0101 1111 1010

Обратите внимание, что это, как правило, не может быть выполнено напрямую, и обычно включает в себя логические или битовые сдвиги ( | и << ). Прикольные вещи.

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

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

Например, 15FA будет расширяться как this:

1 -> 0001
5 -> 0101
F -> 1111
A -> 1010
15FA -> 0001 0101 1111 1010

Обратите внимание, что это, как правило, не может быть выполнено напрямую, и обычно включает в себя логические или битовые сдвиги ( | и << ). Прикольные вещи.

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

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

Например, 15FA будет расширяться как this:

1 -> 0001
5 -> 0101
F -> 1111
A -> 1010
15FA -> 0001 0101 1111 1010

Обратите внимание, что это, как правило, не может быть выполнено напрямую, и обычно включает в себя логические или битовые сдвиги ( | и << ). Прикольные вещи.

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

Например, 15FA будет расширяться как this:

1 -> 0001
5 -> 0101
F -> 1111
A -> 1010
15FA -> 0001 0101 1111 1010

Обратите внимание, что это, как правило, не может быть выполнено напрямую, и обычно включает в себя логические или битовые сдвиги ( | и << ). Прикольные вещи.

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

Например, 15FA будет расширяться как this:

1 -> 0001
5 -> 0101
F -> 1111
A -> 1010
15FA -> 0001 0101 1111 1010

Обратите внимание, что это, как правило, не может быть выполнено напрямую, и обычно включает в себя логические или битовые сдвиги ( | и << ). Прикольные вещи.

Это должно быть сделано напрямую, и обычно включает в себя логические или битовые сдвиги ( | и << ). Прикольные вещи.

Это должно быть сделано напрямую, и обычно включает в себя логические или битовые сдвиги ( | и << ). Прикольные вещи.

2
ответ дан 8 December 2019 в 04:55
поделиться

Обычный подход конвертирует слева направо. Аккумулятор устанавливается в ноль в начале и умножается на 16 перед добавлением эквивалентного значения каждой новой цифры в цикл.

Для функции htoi () , которая ожидает шестнадцатеричные цифры с необязательным начальным значением 0x , начните с пропуска этих символов, если они есть. Прямой контроль значений s [0] и s [1] , вероятно, является наиболее ясным подходом.

Если вы знаете, что цифры находятся в ASCII, то вы можете использовать выражения как s [i] - '0' и s [i] - 'A' + 10 , чтобы преобразовать i-ю цифру в ее целочисленное значение.

Вы, вероятно, хотите сложить все в один случай для здравомыслия.

Редактировать: Изменено * с до s [i] для соответствия с наблюдением, что указатели от будущего с точки зрения этого упражнения.

Обратите внимание, что есть несколько других способов преобразования отдельных цифр в значения. Например, вы можете найти их в векторе из всех цифр (что-то вроде strchr ("0123456789ABCDEF", s [i]) ), построить единую таблицу поиска, проиндексированную кодом символов со значением каждого цифра в каждой позиции ( цифра [s [i]] после того, как int цифра [256] была соответственно инициализирована), используйте оператор switch (s [i]) с меткой case для каждой возможной цифры, как предлагается в другом ответе, или используйте проверки диапазона и арифметику, как я предлагал выше. Надо подумать, что выбрать и почему. Обратите внимание, что это не может быть очевидным выбором, и лучший ответ может быть другим, если ASCII не является вашим набором символов.

1
ответ дан 8 December 2019 в 04:55
поделиться

Вчера я написал такую ​​функцию. Вы можете увидеть мой код ниже.

/* Converting a hex string to integer, assuming the heading 
   0x or 0X has already been removed and pch is not NULL */
int hex_str_to_int(const char* pch) {

    int value = 0;
    int digit = 0;

    for (; *pch; ++pch) {

        if (*pch >= '0' && *pch <= '9') {
            digit = (*pch - '0');
        } else if (*pch >= 'A' && *pch <= 'F') {
            digit = (*pch - 'A' + 10);
        } else if (*pch >= 'a' && *pch <= 'f') {
            digit = (*pch - 'a' + 10);
        } else {
            break;
        }

        // Check for integer overflow
        if ((value *= 16) < 0 || (value += digit) < 0) {
            return INT_MAX;
        }
    }

    return value;
}

Вот код тестирования:

int main(void) {

    printf("%d %d\n", hex_str_to_int("0"), 0x0);
    printf("%d %d\n", hex_str_to_int("A"), 0xA);
    printf("%d %d\n", hex_str_to_int("10"), 0x10);
    printf("%d %d\n", hex_str_to_int("A1"), 0xA1);
    printf("%d %d\n", hex_str_to_int("AB"), 0xAB);
    printf("%d %d\n", hex_str_to_int("100"), 0x100);
    printf("%d %d\n", hex_str_to_int("1A2"), 0x1A2);
    printf("%d %d\n", hex_str_to_int("10A"), 0x10A);
    printf("%d %d\n", hex_str_to_int("7FFFFFF"), 0x7FFFFFF);
    printf("%d %d\n", hex_str_to_int("7FFFFFF1"), 0x7FFFFFF1);
    printf("%d %d\n", hex_str_to_int("7FFFFFF2"), 0x7FFFFFF2);
    printf("%d %d\n", hex_str_to_int("7FFFFFFE"), 0x7FFFFFFE);
    printf("%d %d\n", hex_str_to_int("7FFFFFFF"), 0x7FFFFFFF);
    printf("%d %d\n", hex_str_to_int("80000000"), 0x7FFFFFFF + 1);
    printf("%d %d\n", hex_str_to_int("80000001"), 0x7FFFFFFF + 2);

    printf("%d %d\n", hex_str_to_int("10AX"), 0x10A);   
    printf("%d %d\n", hex_str_to_int("203!"), 0x203);

    return 0;
}

Он выводит следующие значения:

0 0
10 10
16 16
161 161
171 171
256 256
418 418
266 266
134217727 134217727
2147483633 2147483633
2147483634 2147483634
2147483646 2147483646
2147483647 2147483647
2147483647 -2147483648
2147483647 -2147483647
266 266
515 515
-2
ответ дан 8 December 2019 в 04:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: