powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Программирование [игнор отключен] [закрыт для гостей] / не могу разобраться в смысле хеширования
15 сообщений из 15, страница 1 из 1
не могу разобраться в смысле хеширования
    #37048927
testing22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Прочитал про основы хеширования. Там речь идет о массиве, и, как я понял, смысл в том, что функция хеширования позволяет иметь константное время поиска, и при этом относительно небольшой размер массива (то есть, при создании можно не инициализировать массив всеми возможными индексами, которые бы обеспечили уникальность каждому элементу).

Потом, в изучаемом коде встретил словарь (содержащий записи таблицы), при добавлении записи в который, при формировании ключа, используется функция.GetHashCode() с последующим поразрядным сдвигом. Я посмотрел результаты выполнения этого преобразования: к примеру, из числа "654 789 854", в результате этой функции получается число "- 4 658 548 754", то есть, еще большее, чем было до этого и со знаком минус.

В связи с этим возникли вопросы:
1. Зачем использовать GetHashCode(), если при инициализации словаря не требуется указывать его размер (в отличие от массива), то есть размер словаря все равно не будет больше количества содержащихся в нем элементов?
2. Зачем производить манипуляции с числом "654 789 854", если можно просто добавить его в качестве ключа элемента словаря? В изучаемом коде данное число гарантированно уникально?
...
Рейтинг: 0 / 0
не могу разобраться в смысле хеширования
    #37048929
testing22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В изучаемом коде данное число гарантированно уникально.*
...
Рейтинг: 0 / 0
не могу разобраться в смысле хеширования
    #37048955
LINUXER
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
testing221. Зачем использовать GetHashCode(), если при инициализации словаря не требуется указывать его размер (в отличие от массива), то есть размер словаря все равно не будет больше количества содержащихся в нем элементов?
"Не требуется указывать" означает лишь то, что будут использованы значения capacity и load factor по умолчанию.
Память выделяется автоматически по достижению load factorа, т о физически словарь всегда больше содержащихся в нём элементов
Зачем использовать GetHashCode()? например, для организации хеш-таблиц

testing22Я посмотрел результаты выполнения этого преобразования: к примеру, из числа "654 789 854", в результате этой функции получается число "- 4 658 548 754", то есть, еще большее, чем было до этого и со знаком минус.

Как я понял, вы учитесь на .NET. Я посмотрел что GetHashCode - 32bit integer.
"- 4 658 548 754" не помещается в этот тип; я думаю вы что-то напутали

testing222. Зачем производить манипуляции с числом "654 789 854", если можно просто добавить его в качестве ключа элемента словаря? В изучаемом коде данное число гарантированно уникально?
Вы можете переопределить GetHashCode() в вашем классе на функцию, которая вас устраивает.
В каком изучаемом коде? Гарантирована уникальность хеша лишь с определённой верояностью, обычно достаточной.
...
Рейтинг: 0 / 0
не могу разобраться в смысле хеширования
    #37049111
testing22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
LINUXER, конечно, только изучаю.

1. Ну да, capacity и load factor будут работать, но ведь они не будут инициализировать коллекцию, к примеру, в миллиард элементов, как произошло бы в случае с массивом, который нужно будет сразу инициализировать миллиардом элементов. То есть, я вроде бы понимаю смысл ручного хеширования, применительно к массиву. Оно позволяет существенно уменьшить размер создаваемого массива, за счет приведения индексов. Но не понимаю смысл ручного хеширования применительно к словарю. Ручного - то есть с переопределением GetHashCode().

2. Думаю напутал, но не могу понять в чем. Вот мой пример:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
namespace ConsoleApplication35
{
    class Program
    {
        static void Main(string[] args)
        {
            Record Record = new Record();
            Record Record2 = new Record();

            Record.RecordID = 740970205;
            Record.ConnectionID = 1;
            Record2.RecordID = 740970206;
            Record2.ConnectionID = 1;

            int r1 = (Record.ConnectionID + Record.RecordID << 4).GetHashCode(); //получится  -1029378590
            int r2 = (Record2.ConnectionID + Record2.RecordID << 4).GetHashCode(); //получится -1029378574

            Dictionary<int, Record> Dictionary = new Dictionary<int, Record>();

            Dictionary.Add(r1, Record);
            Dictionary.Add(r2, Record2);
        }
    }

    public class Record
    {
        public long RecordID;
        public int ConnectionID;

        public override int GetHashCode()
        {
            return (ConnectionID + RecordID << 4).GetHashCode(); 
        }
    }
}

3. При этом, этот код придумал не я, а встретил у опытного кодера. Им это применяется при генерировании ключа, по которому запись добавляется в словарь при добавлении записи в словарь Dictionary<int, Record>.

При этом, я совершенно уверен, что RecordID является уникальным. Я подумал, что преобразование используется, чтобы уменьшить значение ключа, но:
- значение не уменьшается
- какая разница, какое значение использовать в качестве ключа в словаре? Словарь же сам хеширует ключ при добавлении элемента.

То есть, я не понимаю,
1. Зачем вообще самому хешировать ключ словаря, если ключ сам по себе уникальный?
2. Зачем нужно хешировать в данном случае именно так?
...
Рейтинг: 0 / 0
не могу разобраться в смысле хеширования
    #37049240
testing22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
У меня такая ситуация - есть большая таблица, 200 тыс записей, по которой постоянно проводится поиск. Таблица имеет поле с уникальным значением, состоящее из числа типа long, типа такого "548 567 898". Я эту таблицу представляю в виде Dictionary, и собирался использовать это уникальное поле в качестве ключа. Но наткнулся на пример с использованием хеш-кода в аналогичном случае, и задумался, а правильно ли я собирался сделать, а понять для чего это - не могу.
...
Рейтинг: 0 / 0
не могу разобраться в смысле хеширования
    #37049551
Algol36
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
testing22При этом, я совершенно уверен, что RecordID является уникальным.
В приведенном коде, в качестве ключа используется не Record.RecordID, а пара Record.ConnectionID и Record.RecordID. Вот для того, что бы эту пару отобразить на поле int, используется функция: (Record.ConnectionID + Record.RecordID << 4). Если ConnectionID не превышает 32, то такой ключ будет уникальным для каждой уникальной пары. Вызов GetHashCode() для ключа, по факту, просто преобразет long в int.
...
Рейтинг: 0 / 0
не могу разобраться в смысле хеширования
    #37049591
testing22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Algol36testing22При этом, я совершенно уверен, что RecordID является уникальным.
В приведенном коде, в качестве ключа используется не Record.RecordID, а пара Record.ConnectionID и Record.RecordID. Вот для того, что бы эту пару отобразить на поле int, используется функция: (Record.ConnectionID + Record.RecordID << 4). Если ConnectionID не превышает 32, то такой ключ будет уникальным для каждой уникальной пары. Вызов GetHashCode() для ключа, по факту, просто преобразет long в int.

То есть, поразрядный сдвиг фактически используется для приведения полученного числа в int?

Но зачем может быть нужна такая схема вычисления хеш-кода? Почему-бы просто не добавлять элементы в словарь по полю Record.RecordID, а словарь при добавлении сам посчитает для них хеш-код?

Или это требуется, если есть опасения, что RecordID не уникально? А если оно было бы гарантированно уникально, то переопределять GetHashCode() было бы не нужно?
...
Рейтинг: 0 / 0
не могу разобраться в смысле хеширования
    #37049657
raidan2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
не могу разобраться в смысле хеширования
    #37049731
Algol36
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
testing22Или это требуется, если есть опасения, что RecordID не уникально? А если оно было бы гарантированно уникально, то переопределять GetHashCode() было бы не нужно?Из кода я, например, совершенно не вижу, что RecordID должно быть уникально. У меня есть объект Record с двумя полями RecordID и ConnectionID. Я, как разработчик, данного объекта, совершенно логично предполагаю, что хеш код должен зависеть от всех полей моего объекта. Таким образом, переопределение GetHashCode как сумма своих полей - вполне обосновано. А то, что в каком-то конкретном применении одно из моих полей всегда уникально - это лишь предположения, и меня как разработчика данного класса - не колышат.

PS Только вот к коду, у меня такие замечания:
1)Не очень хорошо брать хеш код ключа, а потом этот хеш использовать как ключ. Это нехорошо, потому что для разных ключей хеш коды могут совпадать, и при помещении в Dictionary двух разных записей по одному ключу выйдет ой.
2)Непонятно, почему Dictionary использует ключ int, а не Record. Второй вариант логичнее, тогда бы как раз задействовалось переопределнное значение GetHashCode.
3)При переопределении метода GetHashCode, настоятельно рекомендуется переопределение и метода Equals. Особенно в случае использования класса как ключа в Dictionary.
...
Рейтинг: 0 / 0
не могу разобраться в смысле хеширования
    #37049769
testing22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Algol36,

Я что-то совсем запутался. Скажите, вот если у меня есть таблица на 200 000 записей с одним гарантированно уникальным полем, то чтобы иметь возмонжость быстрого поиска по ней, я могу сделать вот так и не париться?:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
namespace ConsoleApplication35
{
    class Program
    {
        static void Main(string[] args)
        {
            Record Record = new Record();
            Record Record2 = new Record();

            Record.RecordID = 740970205;
            Record.ConnectionID = 1;
            Record2.RecordID = 740970206;
            Record2.ConnectionID = 1;

            Dictionary<long, Record> Dictionary = new Dictionary<long, Record>();

            Dictionary.Add(Record.RecordID, Record);
            Dictionary.Add(Record2.RecordID, Record2);
        }
    }

    public class Record
    {
        public long RecordID;
        public int ConnectionID;
    }
}
...
Рейтинг: 0 / 0
не могу разобраться в смысле хеширования
    #37049770
testing22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
То есть, чтобы время поиска было O(1)*
...
Рейтинг: 0 / 0
не могу разобраться в смысле хеширования
    #37049777
testing22
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Algol36testing22При этом, я совершенно уверен, что RecordID является уникальным.
В приведенном коде, в качестве ключа используется не Record.RecordID, а пара Record.ConnectionID и Record.RecordID. Вот для того, что бы эту пару отобразить на поле int, используется функция: (Record.ConnectionID + Record.RecordID << 4). Если ConnectionID не превышает 32, то такой ключ будет уникальным для каждой уникальной пары. Вызов GetHashCode() для ключа, по факту, просто преобразет long в int.

А как это посчитать, что если не превышает 32, то будет уникальным для пары?
...
Рейтинг: 0 / 0
не могу разобраться в смысле хеширования
    #37049792
Algol36
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
testing22Algol36,
Я что-то совсем запутался. Скажите, вот если у меня есть таблица на 200 000 записей с одним гарантированно уникальным полем, то чтобы иметь возмонжость быстрого поиска по ней, я могу сделать вот так и не париться?:Можете.
...
Рейтинг: 0 / 0
не могу разобраться в смысле хеширования
    #37061270
mayton1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
testing22
Я что-то совсем запутался. Скажите, вот если у меня есть таблица на 200 000 записей с одним гарантированно уникальным полем, то чтобы иметь возмонжость быстрого поиска по ней, я могу сделать вот так и не париться?:


Да. Это безспорно очень мощная пушка, или даже, гаубица, которая уверенно валит всех воробьев в секторе. Но вы, можете, основываясь на ВАШИХ знаниях о предметной облести, или о задаче сузить диапазон применяемых технологий ровно настолько, чтобы решить вашу задачу. Не больше не меньше. К примеру, если ID-это монотонная последовательность, с известным стартовым значением, то её можно отображать в вектор (дек или очередь) физических адресов (С++) или номеров Объектов (Java/C#) в векторе. Если стоит задача просто проверять СУЩЕСТВОВАНИЕ объекта (ключа), то можно использовать битовую карту и т.п. Не забывайте также о побочных эффетках capacity. Если вовремя не ликвидируете процессы реорганизации хеша "на ходу" то вместо константного отклика рискуете получить таймауты порядка нескольких секунд со 100% оверхедом по CPU. Есть повод заглянуть в сторону B+Tree если для вас важно отсутствие таких артефактов.
...
Рейтинг: 0 / 0
не могу разобраться в смысле хеширования
    #37061331
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
testing22и, как я понял, смысл в том, что функция хеширования позволяет иметь константное время поиска,
Функция хеширования - функция, которая более-менее равномерно "размазывает" различные наборы входных данных по заданному диапазону. Ярче всего смысл этого виден, если данные лежат на внешнем носителе, и "более-менее угадать" место, откуда их читать, гораздо эффективнее, нежели совершать множество обращений к диску, путешествуя по дереву. В целом же подход за счёт траты лишней памяти обеспечивает более быстрое и более стабильное время доступа к данным.
...
Рейтинг: 0 / 0
15 сообщений из 15, страница 1 из 1
Форумы / Программирование [игнор отключен] [закрыт для гостей] / не могу разобраться в смысле хеширования
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]