Сравните два значения, которые содержат произвольное количество битов в C
-
09-09-2019 - |
Вопрос
Я создал систему динамической типизации на C, чтобы создать словарь, который может содержать значения разной ширины в битах.Структура динамического объекта является:
typedef struct
{
void* Pointer;
unsigned char Size;
} Dynamic;
Мне нужно сравнить две из этих динамик, которые содержат показания A2D, а затем сравнить разницу со значением дельты, чтобы определить, произошло ли изменение.Одно из решений, которое я смог придумать, - это преобразовать их в массивы символов и сравнивать их побайт за побайтом, но это нехорошо пахнет.У меня также есть идея создать массив указателей на функции на основе количества байт (или, возможно, типа), которые занимает Динамика, и просто создать функцию сравнения для каждого поддерживаемого типа.Кто-нибудь может предложить другой подход?Такое чувство, что я чего-то не понимаю.
Обновить:
Спасибо, что рассказали мне о memcmp, но у меня все еще есть проблема, как мне получить дельту двух значений?Из того, что я могу сказать, memcmp просто возвращает индикатор того, какое значение больше, а не разницу между ними.
ОБНОВЛЕНИЕ ЗА ОБНОВЛЕНИЕМ:
Оказывается, memcmp бесполезен для меня, потому что архитектура, с которой я компилирую, имеет небольшой конечный код.
Если бы я собирался сам выполнить реализацию bignum, то ephemient кажется правильным решением, но я решил, что просто собираюсь преобразовать значения в максимально возможный тип (т. Е.unsigned long long), с которыми мне придется иметь дело, и просто поработать с математикой, используя их.Я не могу придумать ни одной причины, по которой это не сработало бы, но я признаю, что могу сильно ошибаться, поскольку C / direct манипулирование памятью - не моя сильная сторона.
Решение
Достаточно ли чего-то подобного?
#include <string.h>
int compare(Dynamic *a, Dynamic *b) {
if (a->Size != b->Size) return a->Size - b->Size;
return memcmp(a->Pointer, b->Pointer, a->Size);
}
Создание набора специализированных функций, если они выполняют очень похожие операции, кажется излишеством.
Добавление
Если вы хотите вычислить различия...
int diff(Dynamic *a, Dynamic *b, Dynamic *d) {
int i, borrow = 0;
signed char *ap = a->Pointer, *bp = b->Pointer, *dp = d->Pointer;
assert(a->Size == b->Size && b->Size == d->Size);
for (i = 0; i < a->Size; ap++, bp++, dp++, i++) {
// symmetric difference
*dp = *ap ^ *bp;
// arithmetic difference, assuming little-endian
*dp = borrow += *bp - *ap;
borrow >>= 8;
}
}
Другие советы
Может быть , я тоже чего - то не хватает ... но почему бы вам не использовать memcmp ?
Если вы пытаетесь реализовать функциональность bignum (и вы могли бы рассмотреть чей-то еще (первое попадание Google на "bignum в C")), вы почти наверняка захотите вычислить разницу путем вычитания.Большинство процессоров реализуют compare, выполняя именно это, а затем используя знак результата или нулевую величину для <, >, или ==.
Послушайте, я помешан на математике, я знаю, но основная проблема звучит как "боже, что является естественный порядок этих вещей?"
Являются ли базовые данные необработанными битами, как Bignum?Затем приведите их к unsigned char и сравните их в цикле.Небольшое обдумывание порядка, в котором вы проводите сравнение, сделает его наиболее эффективным.Интересным моментом является то, что длина A ≠ длина B:является ли A≠B тогда по определению, или это числовое значение, которое вы сравниваете, и в этом случае начальные байты 0x00 не являются значимыми?
Если вам нужно просто сравнить для равенства - используйте memcmp().Если вам нужно подсчитать, на сколько битов (или байтов) различаются - реализуйте функцию, аналогичную memcmp(), которая работает через оба массива символов, сравнивает и подсчитывает несовпадающие шаблоны.
Я предполагаю, что размеры переменных битов обусловлены тем, что некоторые значения больше других.Если вы можете гарантировать, что количество битов всегда означает, что номер бита установлен, то вы можете сначала сравнить размеры, и если размеры равны, то выполнить сравнение байтов без знака.Например, для хранения "01" требуется только 1 бит, поэтому его размер будет равен 1, а для хранения "100101" требуется 6 бит, поэтому его размер равен 6.Если размер (a) > размер (b), то (a) > (b).
Хранятся ли они в большом или маленьком конце?