Простой честный алгоритм sh для детерминированного выбора победителя между двумя или более числами? - PullRequest
0 голосов
/ 14 апреля 2020

Я ищу простой алгоритм, который надежно выбирает одного и того же «победителя» из 2 или более разных чисел. Там нет никаких гарантий о порядке, в котором вы получаете номера (но они могут быть отсортированы или что-то подобное). Простым способом решения этой проблемы будет выбор наибольшего / наименьшего числа, однако это не очень справедливый алгоритм, так как он сильно благоприятствует большим / маленьким числам.

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

Последующий вопрос: есть ли класс алгоритмов посвященный этой теме?

Заранее спасибо!

1 Ответ

0 голосов
/ 15 апреля 2020

Расширение комментариев к ответу ...

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

Следующее предложения предназначены для сравнения двух «чисел», чтобы дать полностью детерминированный c, но не очевидный порядок. Для этого извлекается n-битный «ранг» для каждого «числа», подлежащего сравнению, а затем сравнивается «ранг». Если два «числа» имеют одинаковый ранг, то нужно разбить t ie, сравнивая «числа» напрямую.


Использование умножения

Если ваш процессор имеет быстрое умножение на n-бит, то хороший генератор линейных конгруэнтных псевдослучайных чисел (с модулем 2 ^ n) (LCG) даст хорошо выглядящий случайный «ранг» для каждого «числа», за счет одного умножения.

Процесс таков:

  1. "munge" каждого "числа" до n-битов

    Если "число" больше чем длиной n-бит (вы упоминаете ma c -адрес ), тогда первым шагом является преобразование в n-бит. Начните с «ранга», установленного на что-то большое и случайное на вид (столько цифр пи, либо, скажем, е, сколько будет соответствовать). Затем xor в «число» n-битов за раз, вращая «munge» между xors (по крайней мере, 1 бит, но любое нечетное количество бит, возможно, потолок (n / 3)). Вращение сохраняет небольшую разновидность порядка, в котором n-битные части объединяются.

    Если «число» равно n-битам или меньше, начиная с «munge» xor что-то большое-и-большое случайный вид добавляет немного специй.

  2. Создайте "ранг" из каждого "munge".

    Умножьте "munge" на хороший n-битный множитель LCG, чтобы получить n-бит " rank ".

  3. Сравнить и t ie break.

    Сравнить" rank "s, если они не равны, процесс завершен.

    При хорошем LCG маловероятно, что два «числа» дадут одинаковый «ранг» (если только вы не получили только 16-битное умножение).

    Но в любом случае, если два «числа» дают одинаковый «ранг», то, чтобы разбить t ie, вы можете прибегнуть к сравнению чисел. Чтобы сделать это менее очевидным, перед выполнением сравнения вы можете записать каждое «число» в «ранг». Это будет работать, если более двух «чисел» имеют одинаковый «ранг».

    [Помните, что ls-биты LCG выглядят менее случайно, чем ms-биты. Так как это только на ie -брейке, это, вероятно, не имеет значения, но если естественно сравнивать «число» побайтно (например), было бы лучше использовать ms-биты «ранга» ".]


Использование только XOR и Rotate

Если умножение слишком медленное, что в наши дни все еще верно (small ) микроконтроллеры, тогда давайте предположим, что «число» должно обрабатываться 8 или 16 битами за раз.

Начиная с (скажем) «munge» = 157 или «munge» = 31415, шаг (1) выше не будет плохой работой, особенно если «число» составляет три или более n-битных единиц.

Последнее движение: установка «rank» в «munge» xor («munge») повернуто на потолок (n / 3)), не повредит.

Затем действуйте как (3) выше.


Используя CR C

Если ЦП имеет (быстрый) аппаратно-поддерживаемый n-разрядный генератор CR C, то либо:

  • установите "rank" на CR C из "number" "

или:

  • конструкция" munge " как указано выше, и возьмите CR C этого.

Затем выполните (3) выше.

...