Генерация Уникального идентификатора в C++

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

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

9
задан Tim B 9 December 2015 в 12:18
поделиться

9 ответов

Простое решение состоит в том, чтобы использовать целое число на 64 бита, где более низкие 16 битов являются первой координатой вершины, следующие 16 битов является вторым, и так далее. Это будет уникально для всех Ваших вершин, хотя не очень компактный.

Таким образом, вот некоторый код half-assed, чтобы сделать это. Надо надеяться, я разобрался в бросках.

uint64_t generateId( uint16_t v1, uint16_t v2, uint16_t v3, uint16_t v4)
{ 
   uint64_t id;
   id = v1 | (((uint64_t)v2) << 16) | (((uint64_t)v3) << 32) | (((uint64_t)v4) << 48);
   return id;
}

Дополнительно это могло быть сделано с объединением (прекрасная идея от Leon Timmermans, см. комментарий). Очень чистый этот путь:

struct vertex
{
    uint16_t v1;
    uint16_t v2;
    uint16_t v3;
    uint16_t v4;
};

union vertexWithId
{
    vertex v;
    uint64_t id;
};

int main()
{
    vertexWithId vWithId;
    // Setup your vertices
    vWithId.v.v1 = 2;
    vWithId.v.v2 = 5;

    // Your id is automatically setup for you!
    std::cout << "Id is " << vWithId.id << std::endl;
    return 0;
}
5
ответ дан 4 December 2019 в 19:37
поделиться

Иногда самые простые вещи работают лучше всего.

Можно ли просто добавить, что идентификационное поле к Вершине возражает и присваивает ему номер в порядке конструкции?

static int sNextId = 0;
int getNextId() { return ++sNextId; }
8
ответ дан 4 December 2019 в 19:37
поделиться

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

((долго долго) shortNumberX) <<0, 4, 8, или 12

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

Править: забыл добавлять, Вы должны ИЛИ их вместе.

0
ответ дан 4 December 2019 в 19:37
поделиться

Если Вы предпочитаете мобильность, то повышаете:: кортеж хорош:

Вы хотели бы кортеж 4 объектов:

typedef boost::tuple<uint16,uint16,uint16,uint16> VertexID;

Можно присвоиться как это:

VertexID id = boost::make_tuple(1,2,3,4);

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

0
ответ дан 4 December 2019 в 19:37
поделиться

Определение "идентификатора" в вопросе не является действительно четким: необходимо ли использовать его в качестве ключа для быстрого поиска Вершины? Вы могли определить компаратор для std::map (см. ниже для примера),

Необходимо ли смочь дифференцироваться между двумя объектами Вершины с теми же координатами (но отличающийся в другом поле)? Определите некоторую 'идентификационную фабрику' (cfr. шаблон "одиночка"), который генерирует, например, последовательность ints, не связанного со значениями объектов Вершины. - Очень в пути Улан Огня предлагает (но остерегайтесь проблем потокобезопасности!)

По-моему, две вершины с идентичными координатами идентичны. Итак, почему Вам даже был бы нужен дополнительный идентификатор?

Как только Вы определяете 'строгое слабое упорядочивание' на этом типе, можно использовать его в качестве ключа, например, std::map,

struct Vertex {
  typedef short int Value;
  Value v1, v2;

  bool operator<( const Vertex& other ) const {
    return v1 < other.v1 || ( v1 == other.v1 && v2 < other.v2 ) ;
};

Vertex x1 = { 1, 2 };
Vertex x2 = { 1, 3 };
Vertex y1 = { 1, 2 }; // too!

typedef std::set<Vertex> t_vertices;

t_vertices vertices;
vertices.insert( x1 );
vertices.insert( x2 );
vertices.insert( y1 ); // won't do a thing since { 1, 2 } is already in the set.

typedef std::map<Vertex, int> t_vertex_to_counter;
t_vertex_to_counter count;
count[ x1 ]++;
assert( count[x1] == 1 );
assert( count[y1] == 1 );
count[ x2 ]++;
count[ y1 ]++; 
assert( count[x1] == 2 );
assert( count[y1] == 2 );
0
ответ дан 4 December 2019 в 19:37
поделиться

Если Вы находитесь в Windows, Вы могли useCoCreateGUID API, в Linux можно использовать/proc/sys/kernel/random/uuid, можно также посмотреть на 'libuuid'.

0
ответ дан 4 December 2019 в 19:37
поделиться

Если Вы создаете хеш-таблицу, в которой можно сохранить Ваши вершины, я могу думать о нескольких способах избежать коллизий:

  1. Генерируйте идентификаторы непосредственно от входных данных, не выбрасывая битов и используйте хеш-таблицу, которая является достаточно большой для содержания всех возможных идентификаторов. С 64-разрядными идентификаторами последний будет чрезвычайно проблематичен: необходимо будет использовать таблицу, которая меньше, чем диапазон идентификаторов, поэтому необходимо будет иметь дело с коллизиями. Даже с 32-разрядными идентификаторами, Вам были бы нужны хорошо более чем 4 ГБ RAM для осуществления этого без коллизий.
  2. Генерируйте идентификаторы последовательно, поскольку Вы читаете в вершинах. К сожалению, это делает очень дорогим искать ранее вершины чтения для обновления их вероятностей, так как последовательный идентификационный генератор не является хеш-функцией. Если объем данных, используемый для построения Цепи Маркова, значительно меньше, чем объем данных, который Цепь Маркова используется для генерации (или если они являются оба маленькими), это не может быть проблемой.

С другой стороны, Вы могли использовать реализацию хеш-таблицы, которая обрабатывает коллизии для Вас (такие как unordered_map/hash_map), и концентрат на остальной части Вашего приложения.

0
ответ дан 4 December 2019 в 19:37
поделиться

Хорошо единственный способ гарантировать идентификатор уникален, должен сделать, имеют больше идентификационных комбинаций, чем какой Ваши идентификаторы получения от

например, для 2 коротких замыканий (принимающий 16 битов), необходимо использовать интервал на 32 бита

int ID = ((int)short1 << 16) | short2;

и для 4 коротких замыканий Вам был бы нужен интервал на 64 бита и т.д...

С в основном чем-либо еще в значительной степени гарантируются коллизии (несколько вещей могут получить тот же идентификатор).

Однако другой подход (то, которое я думаю, было бы лучше) для получения идентификаторов должен будет раздать их, поскольку вершины вставляются:

unsigned LastId = 0;//global

unsigned GetNewId(){return ++LastId;}

Это также имеет эффект разрешения Вам добавить больше/отличающиеся данные к каждой вершине. Однако, если Вы ожидаете создавать больше, чем 2^32 вершины, не сбрасывая его, это - вероятно, не лучший метод.

0
ответ дан 4 December 2019 в 19:37
поделиться

экспромтом я сказал бы простые числа использования,

id = 3 * value1 + 5 * value2 + .... + somePrime * valueN

Удостоверьтесь, что Вы не переполняете своего идентификационного пространства (долго? долго долго?). Так как у Вас есть постоянное число значений, просто гадят некоторые случайные начала. Не потрудитесь генерировать их, там достаточно доступны в списках для получения Вас идущий некоторое время.

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

-1
ответ дан 4 December 2019 в 19:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: