Как вы имеете дело с дискретными наборами нецелых чисел? - PullRequest
1 голос
/ 08 декабря 2008

У меня есть программа, которая должна сделать карту с проверкой времени компиляции карту из одного известного набора значений в другой известный набор значений:

in      out
------------
8       37
10      61
12      92
13 1/4  109
15 1/4  151
etc

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

Моя текущая мысль (которая мне не нравится) состоит в том, чтобы определить перечисление как

enum Size
{
   _8,
   _10,
   _12,
   _13_25,
   _15_25,
   // etc
}

, а затем настройте его на 2 поиска.

Есть идеи получше?

Редактировать: Моя главная задача - ограничить то, что я могу попытаться посмотреть. Я бы хотел, чтобы даже не скомпилировал , если код может попытаться найти что-то недопустимое.

Множество мало, и время итерации практически не имеет значения.

Я не видел ничего, что принесло бы мне пользу от перечисления, так что пока я с этим согласен. OTOH Я буду следить за этим вопросом.

* Примечание: меня не волнует проблема с указателями, а что нет, просто прямой код, такой как циклы и назначения переменных.


Мельчайший блеск : я упростил вышеприведенное для ясности и общности. У меня на самом деле есть таблица, которая имеет 3 нецелые, неоднородные оси и одну нечисловую ось. И на данный момент я не уверен, в каких направлениях мне понадобится перечислять его.

несколько ссылок, чтобы дать представление о том, что я ищу:

Boost :: SI и моя D версия из такая же идея

Ответы [ 6 ]

1 голос
/ 09 декабря 2008

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

class Size
{
    public decimal Val{get;set;}
    private Size(decimal val){this.val = val;}
    public static Size _8 = new Size(8.0);   
    //...
    public Dictionary<Size, Size> sizeMap = new Dictionary<Size, Size>
    {
        {_8, _37}, 
        //...
    };
}
1 голос
/ 09 декабря 2008

Если ваши входные дроби ограничены каким-либо знаменателем степени 2, вы можете использовать числа с фиксированной точкой в ​​качестве ключей. Для вашего примера, например, используйте 1 бит = 0,25 (умножьте каждый вход на 4) примерно так:

IN maps to Key
--         ---   
8          32   
10         40
12         48 
13 1/4     53
15 1/4     61 

KeyMin= 32

Затем вы можете использовать Key-KeyMin в качестве индекса в разреженном массиве, который содержит значение флага, например -1, для недопустимых записей. Преимущество состоит в том, что это избавляет вас от необходимости перекодировать, если ваши ключи меняются. Недостатком является потеря памяти.

1 голос
/ 08 декабря 2008

Разве вы не можете использовать хэш-карту?

0 голосов
/ 09 декабря 2008

Вот предложение, как вы могли бы решить это. Использование структур и массивов.

typedef struct{
    float input;
    int   output;
}m_lookup;
m_lookup in_out[] = 
{   
    (float) 8   , 37,
    (float)10   , 61,
    (float)12   , 92,
    (float)13.25,109,
    (float)15.25,151,
};

int get_Var(float input)
{
    int i=0;
    for(i=0;i<sizeof(in_out);i++)
        if(in_out[i].input == input)
            return in_out[i].output;
    // Here you could make some special code for your compiler
    return 0;
}
int main(void)
{
    printf("Input 15.25 : Output %d\n",get_Var(15.25));
    printf("Input 13,25 : Output %d\n",get_Var(13.25));
    printf("Illegal input:\n");
    printf("Input 5 : Output %d\n",get_Var(5));
    system( "pause" );
    return 0;
}

Я мог бы, возможно, внести некоторые коррективы, если вы объясните немного больше о мрачной милости.

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

enum Size
{
   i_8=37,
   i_10=61,
   i_12=92,
   i_13_25=109,
   i_15_25=151,
   // etc
}
0 голосов
/ 08 декабря 2008

Идея enum была не слишком страшной, но я бы сделал это динамически. У вас есть массив / список допустимых строк. Индекс в списке строк - это ваш ключ к вашей карте.

// this could be loaded from a file potentially
// notice that the keys have been sorted.
const char* keys[] = { "10", "12", "13 1/4", "15 1/4", "8", 0 };
float values[] = { 61, 92, 109, 151, 37, 0 };
int key_count = 0;
while (keys[key_count]) ++key_count;

bool find(const char* key, float* val) {
   int idx = bsearch(key, keys, sizeof(const char*), key_count, strcmp);
   if (idx < 0) return false;
   *val = values[idx];
   return true;
}

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

0 голосов
/ 08 декабря 2008

Звучит так, будто вы хотите использовать что-то вроде отсортированного двоичного дерева. И поиск, и итерация выполняются быстро, и дерево не будет заботиться о расстоянии между записями.

Если ваши несколько осей независимы, вы можете создать одну для каждой оси.

...