Сравните два значения с произвольным числом битов в C - PullRequest
0 голосов
/ 10 апреля 2009

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

typedef struct
{
    void* Pointer;
    unsigned char Size;   
} Dynamic;

Мне нужно сравнить две из этих динамик, которые содержат показания A2D, а затем сравнить разницу со значением дельты, чтобы определить, произошло ли изменение. Одно из решений, которое мне удалось придумать, - привести их к массивам символов и сравнить их побайтно, но это не пахнет правильно. У меня также есть идея создать массив указателей на функции, основанный на количестве байтов (или, возможно, типа), которые занимает Dynamics, и просто сделать функцию сравнения для каждого поддерживаемого типа. Кто-нибудь может предложить другой подход? Такое ощущение, что я что-то упустил.

UPDATE:

Спасибо, что рассказали мне о memcmp, но у меня все еще есть проблема, как получить дельту двух значений? Из того, что я могу сказать, memcmp просто возвращает индикатор, значение которого больше, а не разницу между ними.

ОБНОВЛЕНИЕ ОБНОВЛЕНИЯ:

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

Если я собирался сделать реализацию bignum самостоятельно, тогда ephemient кажется правильным путем, но я решил, что просто собираюсь запоминать значения в максимально возможный тип (то есть unsigned long long), который у меня будет иметь дело с математикой и просто работать с ними. Я не могу придумать причину, по которой это не сработает, но я понимаю, что могу ошибаться, поскольку прямое манипулирование памятью в C / не является моей сильной стороной.

Ответы [ 6 ]

2 голосов
/ 10 апреля 2009

Достаточно ли что-то подобное?

#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;
    }
}
1 голос
/ 10 апреля 2009

Если вы пытаетесь реализовать функциональность bignum (и вы можете рассмотреть чью-либо (первое попадание Google на "bignum in C")), вы почти наверняка захотите вычислить разницу путем вычитания. Большинство процессоров реализуют сравнение, выполняя только это, а затем используя знак результата или нулевого значения для <,> или ==.

1 голос
/ 10 апреля 2009

Может быть, я тоже что-то упускаю ... но почему бы вам не использовать memcmp?

0 голосов
/ 10 апреля 2009

Я предполагаю, что переменные размеры битов обусловлены тем, что некоторые значения больше, чем другие. Если вы можете гарантировать, что количество бит всегда означает, что бит установлен, то вы можете сначала сравнить размеры, а если размеры равны, то выполнить сравнение байтов без знака. Например, «01» требуется только 1 бит для хранения, поэтому его размер будет равен 1, а «100101» требуется 6 бит для хранения, поэтому его размер равен 6. Если size (a)> size (b), то (a)> (б).

Хранятся ли они в старшем или младшем порядке?

0 голосов
/ 10 апреля 2009

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

0 голосов
/ 10 апреля 2009

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

Являются ли базовые данные необработанными битами, как Bignum? Затем приведите их к неподписанному символу и сравните их в цикле. Небольшая мысль о порядке, в котором вы сравниваете, сделает его наиболее эффективным. Интересный момент, когда длина A & ne; длина B: является ли A & ne; B тогда по определению, или это числовое значение, которое вы сравниваете, и в этом случае начальные байты 0x00 не значимы?

...