Доброго времени суток. Необходимо было разобраться в работе geohash в дерисе, ковыряю исходники. Там геохеш хранится в 52-битном варианте бинарно. Есть функция для вывода геохеша в текстовом виде (base32), находится в geo.c, выглядит примитивно: ====================== ... char *geoalphabet= "0123456789bcdefghjkmnpqrstuvwxyz"; ... int i; for (i = 0; i < 11; i++) { int idx = (hash.bits >> (52-((i+1)*5))) & 0x1f; buf = geoalphabet[idx]; } buf[11] = '\0'; ====================== То есть видим, что просто по 5 бит кодируется каждый символ. В чем собственно вопрос. Я решил написать функцию обратного преобразования из строки в бинарный формат. НО! Обратите внимание, итератор считает до числа 10, внутри цикла прибавляется единица. То есть в теле цикла получается: hash.bits >> (52-((i+1)*5) ====> hash.bits >> (52-(11*5) ===> 52-55 = -3 То есть сдвиг на -3. Такого я не встречал, в инете не нашел. Предполагаю, -3 приводится к unsigned int, значение становится огромным и просто на последней итерации получается ВСЕГДА 0. Вопрос №1: это так? В результате получается, мы всегда теряем предпоследний бит и получаем разницу на 1-3 единицы. Проверил несколько раз: hash origin: 3709594522853587 hash new: 3709594522853584 0000000000001101001011011101101101000111110010111010000011010011 0000000000001101001011011101101101000111110010111010000011010000 Вопрос #2: почему так сделано? Почему идет потеря точности тупо при кодироваии в base32?? Версия редиса 5, не верится, что тут такая тупая ошибка просто.
> Вопрос №1 Не факт, может зависеть от архитектуры. А вообще, сдвиг на отрицательное число - тут UB попахивает. > Вопрос #2 А, может, просто тупая ошибка? Постить баг в трекер не пробовали?