З'єднання двох цілих чисел в одне, унікальним і детермінованим способом


235

Уявіть два натуральних числа A і B. Я хочу об'єднати ці два в одне ціле число C.

Не може бути ніяких інших цілих чисел D і E, які поєднуються в C. Тому поєднання їх з оператором додавання не працює. Наприклад, 30 + 10 = 40 = 40 + 0 = 39 + 1. Наприклад, "31" + "2" = 312 = "3" + "12"

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


10
Ви повинні уточнити, чи маєте на увазі цілі числа в програмному забезпеченні або цілі числа в математиці. У програмному забезпеченні ви вибираєте будь-який цілий тип, і він буде мати розмір, тому у вас є кінцева кількість, тому рішення немає (якщо, звичайно, ваші вхідні дані гарантовано знаходяться в деякому діапазоні, і ваш вихід може бути будь-яке ціле число). У математиці див. Рішення ASk.
Даніель Даранас

Я говорю про обмежені цілі числа в низькому, додатному діапазоні. Скажіть 0 - 10 000
шкода

27
@harm: То як щодо 10,001*A + B?
BlueRaja - Danny Pflughoeft

2
Я знайшов цю функцію PHP: gist.github.com/hannesl/8031402
cakan

Якщо замовлення не має значення, наприклад: (3,12) & (12,3) дають той же результат, я використовую "A + B" + "A * B"
Sodj

Відповіді:


233

Ви шукаєте біективне NxN -> Nвідображення. Вони використовуються, наприклад , для обоча . Перегляньте цей PDF для ознайомлення з так званими функціями сполучення . Вікіпедія вводить специфічну функцію з’єднання, а саме функцію сполучення Кантора :

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

Три зауваження:

  • Як уже зрозуміли інші, якщо ви плануєте реалізувати функцію сполучення, незабаром вам можуть виявитися потрібні довільно великі цілі числа (бігуми).
  • Якщо ви не хочете робити розрізнення між парами (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
Дивіться також функцію Szudzik, пояснену newfal нижче.
OliJG

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

226

Функція спарювання Cantor - це дійсно одна з найкращих ситуацій там, враховуючи її простий, швидкий та просторовий, але тут ще більше опубліковано в 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 біти.

Введіть функцію Szudzik :

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-бітного цілого числа.

Тепер функція Szudzik :

(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-бітових входів може бути настільки непростимим !!

Функція Szudzik :

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-бітним для діапазону підписаних, але все ж краще.

Тепер все це, хоча результат завжди був позитивним. У світі, що підписався, буде ще більше економії місця, якщо ми зможемо перенести половину виведення на негативну вісь . Ви можете зробити це так, як для Szudzik:

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бітового цілого числа, яке є крутим. Я не впевнений, як пройти такий самий шлях для функції з’єднання Cantor, але не намагався настільки, наскільки це не настільки ефективно. Крім того, більше обчислень, що беруть участь у функції сполучення Кантора, означає і її повільність .

Ось реалізація 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 для підписаних цілих чисел?
Arets Paeglis

7
Ця відповідь мене бентежить. Якщо ви хочете зіставити (0,0)через (65535,65535)одне число, тоді a<<16 + bкраще в основному всі способи (швидше, простіше, легше зрозуміти, більш очевидне) . Якщо ви хочете , (-32768,-32768)щоб (327687,327687)замість цього, тільки при умови 32768 першими.
BlueRaja - Danny Pflughoeft

2
@ BlueRaja-DannyPflughoeft ти маєш рацію. Моя відповідь буде справедливою, якщо діапазон не обмежений або невідомий. Я його оновлю. Я написав це до того, як ліміт мав значення. Редагування цієї відповіді давно в моїй думці. Я скоро знайду час.
nawfal

Чи працює функція Szudzik для комбінацій чи перестановок. Здається, перестановки так? Якщо я хочу використовувати для комбінації, чи можу я просто усунути частини алгоритму IF та Else?
Джеймі Маршалл

Ось реалізація Python функції Szudzik, узагальненої до кортежів будь-якої довжини: gitlab.com/snippets/32559
Doctor J

47

Якщо A і B можна виразити двома байтами, їх можна об'єднати на 4 байти. Поставте A на найбільш значущу половину і B на найменш значну половину.

У мові C це дає (припускаючи sizeof (короткий) = 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
@Andy A<<16піде за межі. Це повинно бутиreturn (unsigned int)(A<<16) | (unsigned short)(B);
DanSkeel

15

Це навіть можливо?
Ви поєднуєте два цілих числа. Вони обидва мають діапазон від -2,147,483,648 до 2,147,483,647, але ви приймете лише позитивні результати. Це складає 2147483647 ^ 2 = 4,61169E + 18 комбінацій. Оскільки кожна комбінація повинна бути унікальною І приводить до цілого числа, вам знадобиться якесь магічне ціле число, яке може містити цю кількість чисел.

Або моя логіка хибна?


+1 Це теж я думаю (хоча я зробив обчислення, вказуючи, що порядок A і B не має значення)
lc.

4
Так, ваша логіка правильна за принципом голубів. На жаль, запитувач не вказав, чи обмежене ціле число чи ні.
Невідомо

Так, у мене теж була думка про це, але я вважав, що повідомлення по суті те саме, тому я не намагався згадувати.
Борис Калленс

Крім того, я щойно зрозумів, що мені слід знову взяти підручник з розрахунку шансів (дослівний переклад з голландської).
Борис Калленс

2
@ Boris: Кансрекінг - це "теорія ймовірностей".
Стефан202

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-м просте число, qбуде b+1-м просте число

Тоді результат є 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
ASK

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. Він може кодувати і декодувати. Він працює з нормальними масивами та нумерованими масивами.

#!/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' + ';' + 'B'. Тоді нехай вихід буде хеш (str). Я знаю, що це не математична відповідь, а простий скрипт python (який має вбудовану хеш-функцію) повинен виконати цю роботу.


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

Це хороший момент. Виправити цю проблему можна, просто додавши символ посередині. Так для (8, 11) хеш-рядка "8-11", а для (81, 1) хеш-рядка "81-1". Так загалом для (A, B) хеш-рядка "AB". (Я знаю, це звучить хакі, але це має працювати).
Мадхав Накар

це також неправильно, оскільки це завдання - зіставити два цілих числа на нове ціле число, а не рядок із символом
Leevi L

Я підходжу з точки зору CS, а не з математичного (для математичних рішень дивіться вище відповіді). Я беру два цілих числа, перетворюючи їх у рядок, коли потім перетворюється на ціле число. По суті, так, я зіставляю два цілих числа на нове.
Мадхав Накар

1

Те, що ви пропонуєте, неможливо. У вас завжди будуть зіткнення.

Для того, щоб зіставити два об'єкти в інший єдиний набір, набір карт повинен мати мінімальний розмір кількості очікуваних комбінацій:

Припускаючи 32-бітове ціле число, у вас є 2147483647 додатних цілих чисел. Вибираючи два з них, коли порядок не має значення, і при повторенні виходить 2305843008139952128 комбінацій. Це не чудово вписується в набір 32-бітних цілих чисел.

Однак ви можете відповідати цьому зіставленню в 61 біт. Використовувати 64-бітове ціле число, мабуть, найпростіше. Встановіть високе слово на менше ціле число, а низьке - на велике.


1

Скажіть, у вас є 32-бітове ціле число, чому б просто не перемістити А в першу 16-бітну половину і В в другу?

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 біти), щоб отримати num a:

int a = nums_mapper.GetNumA(bnum);

Щоб отримати число b:

int b = nums_mapper.GetNumB(bnum);

EDIT: bnumможе зберігатися всередині класу. Я цього не робив, бо власними потребами я поділився кодом і сподіваюся, що він буде корисним.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.