Отображение двух целых в одно уникальным и детерминированным способом


235

Представьте два положительных целых числа A и B. Я хочу объединить эти два в одно целое число C.

Не может быть других целых чисел D и E, которые объединяются в C. Поэтому объединение их с помощью оператора сложения не работает. Например, 30 + 10 = 40 = 40 + 0 = 39 + 1 Не работает конкатенация. Например, «31» + «2» = 312 = «3» + «12»

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


10
Вы должны уточнить, имеете ли вы в виду целые числа в программном обеспечении или целые числа в математике. В программном обеспечении вы выбираете любой целочисленный тип, и он будет иметь размер, поэтому у вас есть их конечное число, поэтому решения не существует (если, конечно, ваши входные данные гарантированно не окажутся в некотором диапазоне, а ваши выходные данные могут быть любое целое число). В математике см. Решение ASK.
— Даниэль Даранас

Я говорю о ограниченных целых числах в низком положительном диапазоне. Скажите от 0 до 10000
— вред

27
@harm: А как насчет просто 10,001*A + B?
— BlueRaja - Дэнни Пфлюгофт

2
Я нашел эти функции PHP: gist.github.com/hannesl/8031402
— cakan

Если порядок не имеет значения, например: (3,12) и (12,3) дают тот же результат, я использую «A + B» + «A * B»
— Содж

Ответы:


233

Вы ищете биективное NxN -> Nотображение. Они используются, например, для ласточкиного хвоста . Посмотрите этот PDF для ознакомления с так называемыми функциями сопряжения . Википедия представляет особую функцию сопряжения, а именно функцию сопряжения Кантора :

pi (k1, k2) = 1/2 (k1 + k2) (k1 + k2 + 1) + k2

Три замечания:

  • Как ясно дали понять другие, если вы планируете реализовать функцию сопряжения, вскоре вы можете обнаружить, что вам нужны сколь угодно большие целые числа (bignums).
  • Если вы не хотите проводить различие между парами (a, b) и (b, a), то отсортируйте a и b перед применением функции сопряжения.
  • На самом деле я солгал. Вы ищете биективное ZxZ -> Nотображение. Функция Кантора работает только на неотрицательных числах. Однако это не проблема, потому что легко определить биекцию f : Z -> N, например так:
    • f (n) = n * 2, если n> = 0
    • f (n) = -n * 2 - 1, если n <0

13
+1 Я думаю, что это правильный ответ для неограниченных целых чисел.
— Неизвестно

4
Как я могу получить снова значение k1, k2?
— MinuMaster

3
@MinuMaster: это описано в той же статье в Википедии, в разделе Инвертирование функции сопряжения Кантора .
— Stephan202

4
Смотрите также функцию Шудзика, объясненную newfal ниже.
— OliJG

1
Хотя это верно для неограниченных целых чисел, это не лучше для ограниченных целых чисел. Я думаю, что комментарий @ blue-raja имеет больше смысла.
— Кардасис

226

Функция сопряжения Кантора действительно одна из лучших, учитывая ее простоту, скорость и эффективность использования пространства, но кое-что еще лучше опубликовано в Wolfram Мэтью Шудзиком, здесь . Ограничение функции сопряжения Кантора (относительно) состоит в том, что диапазон закодированных результатов не всегда остается в пределах 2Nбитового целого числа, если входные данные являются Nдвухбитными целыми числами. То есть, если мои входные данные представляют собой 16двухбитные целые числа в диапазоне от 0 to 2^16 -1, то 2^16 * (2^16 -1)возможны комбинации входных данных, поэтому, в соответствии с очевидным принципом Pigeonhole , нам нужен выход по крайней мере такого размера 2^16 * (2^16 -1), который равен 2^32 - 2^16или, другими словами, карте32битовые числа должны быть выполнимыми в идеале. Это не может иметь мало практического значения в мире программирования.

Функция сопряжения Кантора :

(a + b) * (a + b + 1) / 2 + a; where a, b >= 0

Отображение для двух максимально 16-битных целых чисел (65535, 65535) будет 8589803520, которое, как вы видите, не может быть вписано в 32 бита.

Введите функцию Шудзика :

a >= b ? a * a + a + b : a + b * b;  where a, b >= 0

Отображение для (65535, 65535) теперь будет 4294967295, которое, как вы видите, является 32-битным (от 0 до 2 ^ 32 -1) целым числом. Вот где это решение идеально, оно просто использует каждую точку в этом пространстве, поэтому ничто не может быть более эффективным.


Теперь, учитывая тот факт, что мы обычно имеем дело со знаковыми реализациями чисел различных размеров в языках / инфраструктурах, давайте рассмотрим signed 16битовые целые числа, начиная от -(2^15) to 2^15 -1(позже мы увидим, как расширить даже выходной поток, чтобы охватить диапазон со знаком). Так как aи bдолжны быть положительными, они варьируются от 0 to 2^15 - 1.

Функция сопряжения Кантора :

Отображение для двух максимальных 16-разрядных целых чисел со знаком (32767, 32767) будет 2147418112, что немного меньше максимального значения для 32-разрядного целого числа со знаком.

Теперь функция Шудзика :

(32767, 32767) => 1073741823, намного меньше ..

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

Функция сопряжения Кантора :

A = a >= 0 ? 2 * a : -2 * a - 1;
B = b >= 0 ? 2 * b : -2 * b - 1;
(A + B) * (A + B + 1) / 2 + A;

(-32768, -32768) => 8589803520, то есть Int64. 64-битный выход для 16-битных входов может быть таким непростительным !!

Функция Шудзика :

A = a >= 0 ? 2 * a : -2 * a - 1;
B = b >= 0 ? 2 * b : -2 * b - 1;
A >= B ? A * A + A + B : A + B * B;

(-32768, -32768) => 4294967295, который является 32-битным для диапазона без знака или 64-битным для диапазона со знаком, но все же лучше.

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

A = a >= 0 ? 2 * a : -2 * a - 1;
B = b >= 0 ? 2 * b : -2 * b - 1;
C = (A >= B ? A * A + A + B : A + B * B) / 2;
a < 0 && b < 0 || a >= 0 && b >= 0 ? C : -C - 1;

(-32768, 32767) => -2147483648

(32767, -32768) => -2147450880

(0, 0) => 0 

(32767, 32767) => 2147418112

(-32768, -32768) => 2147483647

Что я делаю: применив вес 2к входам и пройдя через функцию, затем разделю выходной сигнал на два и перенесу некоторые из них на отрицательную ось, умножив на -1.

См. Результаты, для любого ввода в диапазоне числа 16битов со знаком, выход лежит в пределах 32целого числа битов со знаком, что здорово. Я не уверен, как сделать то же самое для функции сопряжения Кантора, но не пытался так сильно, как это не так эффективно. Кроме того, чем больше вычислений, связанных с функцией сопряжения Кантора, тем медленнее и ее .

Вот реализация C #.

public static long PerfectlyHashThem(int a, int b)
{
    var A = (ulong)(a >= 0 ? 2 * (long)a : -2 * (long)a - 1);
    var B = (ulong)(b >= 0 ? 2 * (long)b : -2 * (long)b - 1);
    var C = (long)((A >= B ? A * A + A + B : A + B * B) / 2);
    return a < 0 && b < 0 || a >= 0 && b >= 0 ? C : -C - 1;
}

public static int PerfectlyHashThem(short a, short b)
{
    var A = (uint)(a >= 0 ? 2 * a : -2 * a - 1);
    var B = (uint)(b >= 0 ? 2 * b : -2 * b - 1);
    var C = (int)((A >= B ? A * A + A + B : A + B * B) / 2);
    return a < 0 && b < 0 || a >= 0 && b >= 0 ? C : -C - 1;
}

Поскольку промежуточные вычисления могут превышать пределы 2Nцелого числа со знаком, я использовал 4Nцелочисленный тип (последнее деление на 2возвращает результат в 2N).

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


5
Что будет модифицированной unhash-функцией для целых чисел со знаком?
— Арец Пэглис

7
Этот ответ смущает меня. Если вы хотите отобразить (0,0)через (65535,65535)к одному числу, то a<<16 + bлучше в основном во всех отношениях (быстрее, проще, легче понять, что более очевидно) . Если вы хотите , (-32768,-32768)чтобы (327687,327687)вместо этого, только при условии 32768 первыми.
— BlueRaja - Дэнни Пфлугхофт

2
@ BlueRaja-DannyPflughoeft ты прав. Мой ответ будет действительным, если диапазон не ограничен или неизвестен. Я обновлю это. Я написал это прежде, чем предел имел значение для меня. Редактирование этого ответа давно было в моей голове. Я найду время в ближайшее время.
— Nawfal

Работает ли функция Шудзика для комбинаций или перестановок. Вроде бы перестановки не так ли? Если я хочу использовать для комбинации, могу ли я просто исключить части алгоритма IF и Else?
— Джейми Маршалл

Вот реализация Python функции Шудзика, обобщенной на кортежи любой длины: gitlab.com/snippets/32559
— Доктор J

47

Если A и B могут быть выражены 2 байтами, вы можете объединить их в 4 байта. Поместите A в самую значительную половину, а B в самую младшую.

В языке C это дает (при условии, что sizeof (short) = 2 и sizeof (int) = 4):

int combine(short A, short B)
{
    return A<<16 | B;
}

short getA(int C)
{
    return C>>16;
}

short getB(int C)
{
    return C & 0xFFFF;
}

3
combine()следует return (unsigned short)(A<<16) | (unsigned short)(B); так , что отрицательные числа могут быть упакованы надлежащим образом .
— Энди

2
@ Энди A<<16выйдет за пределы. Это должно бытьreturn (unsigned int)(A<<16) | (unsigned short)(B);
— DanSkeel

15

Это вообще возможно?
Вы объединяете два целых числа. Оба имеют диапазон от -2 147 483 648 до 2 147 483 647, но вы будете принимать только положительные результаты. Это составляет 2147483647 ^ 2 = 461169E + 18 комбинаций. Поскольку каждая комбинация должна быть уникальной И приводить к целому числу, вам понадобится какое-то магическое целое число, которое может содержать это количество чисел.

Или моя логика ошибочна?


+1 Я тоже так думаю (хотя я сделал расчет, говоря, что порядок A и B не имеет значения)
— lc.

4
Да, ваша логика верна по принципу голубя. К сожалению, спрашивающий не уточнил, является ли целое число ограниченным или нет.
— неизвестно

Да, у меня тоже была эта запоздалая мысль, но я думал, что сообщение по сути то же самое, поэтому я не стал вспоминать.
— Борис Калленс

Кроме того, я только что понял, что должен снова забрать учебники для расчета шансов (буквальный перевод с голландского).
— Борис Калленс

2
@Boris: Kansrekening - это «теория вероятностей».
— Stephan202

8

Стандартный математический способ для натуральных чисел состоит в использовании уникальности простой факторизации.

f( x, y ) -> 2^x * 3^y

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

Вы можете изменить это, чтобы иметь дело с отрицательным xи yкодируя флаги со степенями 5 и 7 членов.

например

f( x, y ) -> 2^|x| * 3^|y| * 5^(x<0) * 7^(y<0)

Математика в порядке. Но, как говорит Борис, если вы хотите запустить это как компьютерную программу, вы должны принять во внимание конечность машины. Алгоритм будет работать правильно для подмножества целых чисел, представленных на соответствующем компьютере.
— Ювал Ф

2
Я утверждал это во втором абзаце. Теги в вопросе обозначают «алгоритм», «математический» и «детерминированный», а не какой-либо конкретный язык. Диапазон ввода не может быть ограничен, и среда может иметь неограниченный целочисленный тип «bigint».
— CB Bailey

8

Пусть число aбудет первым, bвторым. Позвольте pбыть a+1-th простое число, qбудет b+1-th простое число

Тогда результат pq, если a<b,или 2pqесли a>b. Если a=bда, то будет p^2.


4
Я сомневаюсь, что вы хотели бы решение NP.
— user44242

1
Разве это не дает одинаковый результат для a = 5, b = 14 и a = 6, b = 15?
— Ливен Керсмакерс

3
Два произведения двух разных простых чисел не могут иметь одинаковый результат (разложение по уникальному первичному фактору) a = 5, b = 14 -> результат равен 13 * 47 = 611 a = 6, b = 15 -> результат равен 17 * 53 = 901
— спросите

4

Не так сложно построить отображение:

   1 2 3 4 5 используйте это отображение, если (a, b)! = (B, a)
1 0 1 3 6 10
2 2 4 7 11 16
3 5 8 12 17 23
4 9 13 18 24 31
5 14 19 25 32 40

   1 2 3 4 5 используйте это отображение, если (a, b) == (b, a) (зеркало)
1 0 1 2 4 6
2 1 3 5 7 10
3 2 5 8 11 14
4 4 8 11 15 19
5 6 10 14 19 24


    0 1 -1 2 -2 используйте это, если вам нужен отрицательный / положительный
 0 0 1 2 4 6
 1 1 3 5 7 10
-1 2 5 8 11 14
 2 4 8 11 15 19
-2 6 10 14 19 24

Выяснить, как получить значение для произвольного a, b немного сложнее.


4

f(a, b) = s(a+b) + a, где s(n) = n*(n+1)/2

  • Это функция - она ​​детерминированная.
  • Это также инъективно - f отображает разные значения для разных (a, b) пар. Вы можете доказать это, используя факт s(a+b+1)-s(a+b) = a+b+1 < a.
  • Он возвращает довольно маленькие значения - хорошо, если вы собираетесь использовать его для индексации массива, так как массив не должен быть большим.
  • Это удобно для кэша - если две (a, b) пары близки друг к другу, то f отображает числа, которые близки друг к другу (по сравнению с другими методами).

Я не понял, что Вы подразумеваете под:

должен всегда давать целое число на положительной или отрицательной стороне целых чисел

Как я могу написать (больше чем), (меньше чем) символы на этом форуме?


2
Больше чем и меньше чем символы должны хорошо работать в backtick escapes.
— TRiG

Это эквивалентно функции сопряжения Кантора, и поэтому не работает с отрицательными целыми числами.
— Давор Йосипович

4

Хотя ответ Stephan202 является единственным действительно общим, для целых чисел в ограниченном диапазоне вы можете добиться большего успеха. Например, если ваш диапазон составляет 0,10 000, то вы можете сделать:

#define RANGE_MIN 0
#define RANGE_MAX 10000

unsigned int merge(unsigned int x, unsigned int y)
{
    return (x * (RANGE_MAX - RANGE_MIN + 1)) + y;
}

void split(unsigned int v, unsigned int &x, unsigned int &y)
{
    x = RANGE_MIN + (v / (RANGE_MAX - RANGE_MIN + 1));
    y = RANGE_MIN + (v % (RANGE_MAX - RANGE_MIN + 1));
}

Результаты могут помещаться в одно целое число в диапазоне до квадратного корня из числа целочисленных типов. Это упаковывает немного более эффективно, чем более общий метод Stephan202. Также значительно проще декодировать; не требующий квадратных корней, для начала :)


Это случайно возможно для поплавков?
— Лукас

4

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

  1. Вот неупорядоченная функция сопряжения :

    <x, y> = x * y + trunc((|x - y| - 1)^2 / 4) = <y, x>
    
  2. Для x ≠ y вот уникальная неупорядоченная функция сопряжения :

    <x, y> = if x < y:
               x * (y - 1) + trunc((y - x - 2)^2 / 4)
             if x > y:
               (x - 1) * y + trunc((x - y - 2)^2 / 4)
           = <y, x>
    

3

Проверьте это: http://en.wikipedia.org/wiki/Pigeonhole_principle . Если A, B и C одного типа, это невозможно сделать. Если A и B являются 16-разрядными целыми числами, а C - 32-разрядными, то вы можете просто использовать сдвиг.

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


2

Вот расширение кода @DoctorJ на неограниченные целые числа, основанное на методе, заданном @nawfal. Он может кодировать и декодировать. Он работает с обычными массивами и массивами numpy.

#!/usr/bin/env python
from numbers import Integral    

def tuple_to_int(tup):
    """:Return: the unique non-negative integer encoding of a tuple of non-negative integers."""
    if len(tup) == 0:  # normally do if not tup, but doesn't work with np
        raise ValueError('Cannot encode empty tuple')
    if len(tup) == 1:
        x = tup[0]
        if not isinstance(x, Integral):
            raise ValueError('Can only encode integers')
        return x
    elif len(tup) == 2:
        # print("len=2")
        x, y = tuple_to_int(tup[0:1]), tuple_to_int(tup[1:2])  # Just to validate x and y

        X = 2 * x if x >= 0 else -2 * x - 1  # map x to positive integers
        Y = 2 * y if y >= 0 else -2 * y - 1  # map y to positive integers
        Z = (X * X + X + Y) if X >= Y else (X + Y * Y)  # encode

        # Map evens onto positives
        if (x >= 0 and y >= 0):
            return Z // 2
        elif (x < 0 and y >= 0 and X >= Y):
            return Z // 2
        elif (x < 0 and y < 0 and X < Y):
            return Z // 2
        # Map odds onto negative
        else:
            return (-Z - 1) // 2
    else:
        return tuple_to_int((tuple_to_int(tup[:2]),) + tuple(tup[2:]))  # ***speed up tuple(tup[2:])?***


def int_to_tuple(num, size=2):
    """:Return: the unique tuple of length `size` that encodes to `num`."""
    if not isinstance(num, Integral):
        raise ValueError('Can only encode integers (got {})'.format(num))
    if not isinstance(size, Integral) or size < 1:
        raise ValueError('Tuple is the wrong size ({})'.format(size))
    if size == 1:
        return (num,)
    elif size == 2:

        # Mapping onto positive integers
        Z = -2 * num - 1 if num < 0 else 2 * num

        # Reversing Pairing
        s = isqrt(Z)
        if Z - s * s < s:
            X, Y = Z - s * s, s
        else:
            X, Y = s, Z - s * s - s

        # Undoing mappint to positive integers
        x = (X + 1) // -2 if X % 2 else X // 2  # True if X not divisible by 2
        y = (Y + 1) // -2 if Y % 2 else Y // 2  # True if Y not divisible by 2

        return x, y

    else:
        x, y = int_to_tuple(num, 2)
        return int_to_tuple(x, size - 1) + (y,)


def isqrt(n):
    """":Return: the largest integer x for which x * x does not exceed n."""
    # Newton's method, via http://stackoverflow.com/a/15391420
    x = n
    y = (x + 1) // 2
    while y < x:
        x = y
        y = (x + n // x) // 2
    return x

2

Как насчет чего-то гораздо более простого: учитывая два числа, A и B позволяют str быть конкатенацией: 'A' + ';' + «Б». Тогда пусть выводом будет хеш (str). Я знаю, что это не математический ответ, а простой скрипт на python (который имеет встроенную хэш-функцию) должен выполнить эту работу.


2
но (8,11) и (81,1) отображаются на одно и то же число 811
— Леви L

Это хороший момент. Вы можете решить эту проблему, просто добавив символ в середине. Таким образом, для (8, 11) хеш-строки «8-11» и для (81, 1) хеш-строки «81-1». Так что в общем случае для (A, B) хэшируется строка «AB». (Я знаю, это звучит глупо, но это должно работать).
— Мадхав Накар

Это также неправильно, потому что эта задача состоит в том, чтобы отобразить два целых числа в новое целое число, а не строку с символом
— Leevi L

Я пришел с точки зрения CS, а не с математической точки зрения (для математических решений посмотрите выше ответы). Я беру два целых числа, превращая их в строку, а затем превращаю в целое число. По сути, да, я сопоставляю два целых числа с новым.
— Мадхав Накар

1

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

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

Предполагая 32-разрядное целое число, у вас есть 2147483647 натуральных чисел. Выбор двух из них, где порядок не имеет значения, с повторением дает 2305843008139952128 комбинаций. Это не очень хорошо вписывается в набор 32-битных целых чисел.

Однако вы можете разместить это отображение в 61 бит. Использование 64-разрядного целого числа, вероятно, проще всего. Установите старшее слово на меньшее целое и младшее слово на большее.


1

Скажем, у вас есть 32-разрядное целое число, почему бы просто не переместить A в первую 16-разрядную половину, а B в другую?

def vec_pack(vec):
    return vec[0] + vec[1] * 65536;


def vec_unpack(number):
    return [number % 65536, number // 65536];

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

a = vec_pack([2,4])
b = vec_pack([1,2])

print(vec_unpack(a+b)) # [3, 6] Vector addition
print(vec_unpack(a-b)) # [1, 2] Vector subtraction
print(vec_unpack(a*2)) # [4, 8] Scalar multiplication

0

давайте иметь два числа B и C, кодирующие их в одно число A

A = B + C * N

где

B = A% N = B

C = A / N = C


2
Как вы выбираете N, чтобы сделать это представление уникальным? Если вы решите эту проблему, чем этот ответ будет отличаться от приведенного выше?
— чернослив

Вы должны добавить, что N должно быть больше, чем B и C.
— Радослав Стоянов

0

Учитывая положительные целые числа A и B, пусть D = количество цифр A имеет, а E = количество цифр B имеет. Результатом может быть объединение D, 0, E, 0, A и B.

Пример: A = 300, B = 12. D = 3, E = 2, результат = 302030012. Это использует тот факт, что единственным числом, начинающимся с 0, является 0,

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

Минусы: размер результатов является проблемой. Но это нормально, почему мы в любом случае храним неограниченные целые числа в компьютере.


0

Если вы хотите больше контроля, например, выделите биты X для первого числа и биты Y для второго числа, вы можете использовать этот код:

class NumsCombiner
{

    int num_a_bits_size;
    int num_b_bits_size;

    int BitsExtract(int number, int k, int p)
    {
        return (((1 << k) - 1) & (number >> (p - 1)));
    }

public:
    NumsCombiner(int num_a_bits_size, int num_b_bits_size)
    {
        this->num_a_bits_size = num_a_bits_size;
        this->num_b_bits_size = num_b_bits_size;
    }

    int StoreAB(int num_a, int num_b)
    {
        return (num_b << num_a_bits_size) | num_a;
    }

    int GetNumA(int bnum)
    {
        return BitsExtract(bnum, num_a_bits_size, 1);
    }

    int GetNumB(int bnum)
    {
        return BitsExtract(bnum, num_b_bits_size, num_a_bits_size + 1);
    }
};

Я использую всего 32 бита. Идея здесь в том, что если вы хотите, например, чтобы первое число было до 10 бит, а второе число до 12 бит, вы можете сделать это:

NumsCombiner nums_mapper(10/*bits for first number*/, 12/*bits for second number*/);

Теперь вы можете хранить в num_aмаксимальном количестве 2^10 - 1 = 1023и в num_bмаксимальном значении 2^12 - 1 = 4095.

Чтобы установить значение для числа A и числа B:

int bnum = nums_mapper.StoreAB(10/*value for a*/, 12 /*value from b*/);

Теперь bnumвсе биты (всего 32 бита. Вы можете изменить код, чтобы использовать 64 бита). Чтобы получить число:

int a = nums_mapper.GetNumA(bnum);

Чтобы получить число б:

int b = nums_mapper.GetNumB(bnum);

РЕДАКТИРОВАТЬ: bnumможет храниться в классе. Я этого не делал, потому что для собственных нужд я поделился кодом и надеюсь, что он будет полезен.

Спасибо за источник: https://www.geeksforgeeks.org/extract-k-bits-given-position-number/ за функцию извлечения битов и спасибо также за mouvicielответ в этом посте. Используя эти источники, я смог найти более продвинутое решение.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.