Перевести код из 5 цифр в 3 символа - PullRequest
0 голосов
/ 29 мая 2018

У меня есть код, состоящий из пяти десятичных знаков, мне нужно сохранить (сжать) его в поле, которое может содержать только 3 буквенно-цифровых печатных символа ascii.Возможно ли иметь двунаправленное преобразование между двумя полями?Как в С?

Ответы [ 2 ]

0 голосов
/ 29 мая 2018

Чтобы представить любое число от 0 до 99999 с тремя цифрами, вам необходимо преобразовать число из основания 10 в более высокое основание b , где b 3 > 99999.

Наименьшее основание, соответствующее этому требованию, составляет 47. На выбор доступно 97 печатных символов ASCII, поэтому, очевидно, проблем нет.

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

Следующий код должен работать.Он не оптимизирован, но должен быть достаточно быстрым, если вам не нужно конвертировать миллионы чисел в секунду.

#define ALPHABET "26789BCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz"
#define LEN_ALPH 47

unsigned int asc2int(char *s) {
    unsigned int i, result = 0;
    while (*s) {
        for (i=0; i<LEN_ALPH; i++) {
            if (*s == ALPHABET[i]) break;
        }
        if (i == LEN_ALPH) return 0; /* Illegal character in input */
        result = result * LEN_ALPH + i;  /* TODO: Check for overflow */
        s++;
    }
    return result;
}

char *int2asc(unsigned int n) {
    static char result[7];  /* Should be sufficient for any 32-bit input */
    char *ptr = result+6;
    *ptr = '\0';
    if (n == 0) {
        *(--ptr) = ALPHABET[0];
    }
    else {
        while (n) {
            *(--ptr) = ALPHABET[n % LEN_ALPH];
            n /= LEN_ALPH;
        }
    }
    return ptr;
}


int main() {
    unsigned int tests[10] = { 0, 1, 10, 100, 1000, 10000, 11111, 12345, 54321, 99999 };
    unsigned int i, n;
    char *s;

    /* Test with selected numbers */
    for (i=0; i<10; i++) {
        s = int2asc(tests[i]);
        n = asc2int(s);
        printf("%u -> %s -> %u\n", tests[i], s, n);
    }

    /* Test all numbers */
    for (i=0; i<100000; i++) {
        if (asc2int(int2asc(i)) != i) {
            printf("Failed at i=%u\n", i);
            return 1;
        }
    }
    return 0;
}
0 голосов
/ 29 мая 2018

Это невозможно, если только вы не хотите использовать буквы верхнего и нижнего регистра, а также цифры.

Существует 90 000 таких кодов с ровно 5 десятичными знаками, а корень куба этого округленного числа45. Таким образом, один буквенно-цифровой символ должен иметь 45 возможностей.

Итак, в вашем случае рассмотрите возможность использования кодировки Base64, которая сама по себе стала стандартом: https://en.wikipedia.org/wiki/Base64

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...