|
|
|
не могу разобраться в смысле хеширования
|
|||
|---|---|---|---|
|
#18+
Прочитал про основы хеширования. Там речь идет о массиве, и, как я понял, смысл в том, что функция хеширования позволяет иметь константное время поиска, и при этом относительно небольшой размер массива (то есть, при создании можно не инициализировать массив всеми возможными индексами, которые бы обеспечили уникальность каждому элементу). Потом, в изучаемом коде встретил словарь (содержащий записи таблицы), при добавлении записи в который, при формировании ключа, используется функция.GetHashCode() с последующим поразрядным сдвигом. Я посмотрел результаты выполнения этого преобразования: к примеру, из числа "654 789 854", в результате этой функции получается число "- 4 658 548 754", то есть, еще большее, чем было до этого и со знаком минус. В связи с этим возникли вопросы: 1. Зачем использовать GetHashCode(), если при инициализации словаря не требуется указывать его размер (в отличие от массива), то есть размер словаря все равно не будет больше количества содержащихся в нем элементов? 2. Зачем производить манипуляции с числом "654 789 854", если можно просто добавить его в качестве ключа элемента словаря? В изучаемом коде данное число гарантированно уникально? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.01.2011, 03:00 |
|
||
|
не могу разобраться в смысле хеширования
|
|||
|---|---|---|---|
|
#18+
В изучаемом коде данное число гарантированно уникально.* ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.01.2011, 03:02 |
|
||
|
не могу разобраться в смысле хеширования
|
|||
|---|---|---|---|
|
#18+
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() в вашем классе на функцию, которая вас устраивает. В каком изучаемом коде? Гарантирована уникальность хеша лишь с определённой верояностью, обычно достаточной. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.01.2011, 08:27 |
|
||
|
не могу разобраться в смысле хеширования
|
|||
|---|---|---|---|
|
#18+
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. 3. При этом, этот код придумал не я, а встретил у опытного кодера. Им это применяется при генерировании ключа, по которому запись добавляется в словарь при добавлении записи в словарь Dictionary<int, Record>. При этом, я совершенно уверен, что RecordID является уникальным. Я подумал, что преобразование используется, чтобы уменьшить значение ключа, но: - значение не уменьшается - какая разница, какое значение использовать в качестве ключа в словаре? Словарь же сам хеширует ключ при добавлении элемента. То есть, я не понимаю, 1. Зачем вообще самому хешировать ключ словаря, если ключ сам по себе уникальный? 2. Зачем нужно хешировать в данном случае именно так? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.01.2011, 15:00 |
|
||
|
не могу разобраться в смысле хеширования
|
|||
|---|---|---|---|
|
#18+
У меня такая ситуация - есть большая таблица, 200 тыс записей, по которой постоянно проводится поиск. Таблица имеет поле с уникальным значением, состоящее из числа типа long, типа такого "548 567 898". Я эту таблицу представляю в виде Dictionary, и собирался использовать это уникальное поле в качестве ключа. Но наткнулся на пример с использованием хеш-кода в аналогичном случае, и задумался, а правильно ли я собирался сделать, а понять для чего это - не могу. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.01.2011, 17:50 |
|
||
|
не могу разобраться в смысле хеширования
|
|||
|---|---|---|---|
|
#18+
testing22При этом, я совершенно уверен, что RecordID является уникальным. В приведенном коде, в качестве ключа используется не Record.RecordID, а пара Record.ConnectionID и Record.RecordID. Вот для того, что бы эту пару отобразить на поле int, используется функция: (Record.ConnectionID + Record.RecordID << 4). Если ConnectionID не превышает 32, то такой ключ будет уникальным для каждой уникальной пары. Вызов GetHashCode() для ключа, по факту, просто преобразет long в int. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.01.2011, 22:45 |
|
||
|
не могу разобраться в смысле хеширования
|
|||
|---|---|---|---|
|
#18+
Algol36testing22При этом, я совершенно уверен, что RecordID является уникальным. В приведенном коде, в качестве ключа используется не Record.RecordID, а пара Record.ConnectionID и Record.RecordID. Вот для того, что бы эту пару отобразить на поле int, используется функция: (Record.ConnectionID + Record.RecordID << 4). Если ConnectionID не превышает 32, то такой ключ будет уникальным для каждой уникальной пары. Вызов GetHashCode() для ключа, по факту, просто преобразет long в int. То есть, поразрядный сдвиг фактически используется для приведения полученного числа в int? Но зачем может быть нужна такая схема вычисления хеш-кода? Почему-бы просто не добавлять элементы в словарь по полю Record.RecordID, а словарь при добавлении сам посчитает для них хеш-код? Или это требуется, если есть опасения, что RecordID не уникально? А если оно было бы гарантированно уникально, то переопределять GetHashCode() было бы не нужно? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.01.2011, 23:17 |
|
||
|
не могу разобраться в смысле хеширования
|
|||
|---|---|---|---|
|
#18+
... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.01.2011, 23:54 |
|
||
|
не могу разобраться в смысле хеширования
|
|||
|---|---|---|---|
|
#18+
testing22Или это требуется, если есть опасения, что RecordID не уникально? А если оно было бы гарантированно уникально, то переопределять GetHashCode() было бы не нужно?Из кода я, например, совершенно не вижу, что RecordID должно быть уникально. У меня есть объект Record с двумя полями RecordID и ConnectionID. Я, как разработчик, данного объекта, совершенно логично предполагаю, что хеш код должен зависеть от всех полей моего объекта. Таким образом, переопределение GetHashCode как сумма своих полей - вполне обосновано. А то, что в каком-то конкретном применении одно из моих полей всегда уникально - это лишь предположения, и меня как разработчика данного класса - не колышат. PS Только вот к коду, у меня такие замечания: 1)Не очень хорошо брать хеш код ключа, а потом этот хеш использовать как ключ. Это нехорошо, потому что для разных ключей хеш коды могут совпадать, и при помещении в Dictionary двух разных записей по одному ключу выйдет ой. 2)Непонятно, почему Dictionary использует ключ int, а не Record. Второй вариант логичнее, тогда бы как раз задействовалось переопределнное значение GetHashCode. 3)При переопределении метода GetHashCode, настоятельно рекомендуется переопределение и метода Equals. Особенно в случае использования класса как ключа в Dictionary. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.01.2011, 00:55 |
|
||
|
не могу разобраться в смысле хеширования
|
|||
|---|---|---|---|
|
#18+
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. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.01.2011, 01:33 |
|
||
|
не могу разобраться в смысле хеширования
|
|||
|---|---|---|---|
|
#18+
То есть, чтобы время поиска было O(1)* ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.01.2011, 01:34 |
|
||
|
не могу разобраться в смысле хеширования
|
|||
|---|---|---|---|
|
#18+
Algol36testing22При этом, я совершенно уверен, что RecordID является уникальным. В приведенном коде, в качестве ключа используется не Record.RecordID, а пара Record.ConnectionID и Record.RecordID. Вот для того, что бы эту пару отобразить на поле int, используется функция: (Record.ConnectionID + Record.RecordID << 4). Если ConnectionID не превышает 32, то такой ключ будет уникальным для каждой уникальной пары. Вызов GetHashCode() для ключа, по факту, просто преобразет long в int. А как это посчитать, что если не превышает 32, то будет уникальным для пары? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.01.2011, 01:38 |
|
||
|
не могу разобраться в смысле хеширования
|
|||
|---|---|---|---|
|
#18+
testing22Algol36, Я что-то совсем запутался. Скажите, вот если у меня есть таблица на 200 000 записей с одним гарантированно уникальным полем, то чтобы иметь возмонжость быстрого поиска по ней, я могу сделать вот так и не париться?:Можете. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.01.2011, 01:48 |
|
||
|
не могу разобраться в смысле хеширования
|
|||
|---|---|---|---|
|
#18+
testing22 Я что-то совсем запутался. Скажите, вот если у меня есть таблица на 200 000 записей с одним гарантированно уникальным полем, то чтобы иметь возмонжость быстрого поиска по ней, я могу сделать вот так и не париться?: Да. Это безспорно очень мощная пушка, или даже, гаубица, которая уверенно валит всех воробьев в секторе. Но вы, можете, основываясь на ВАШИХ знаниях о предметной облести, или о задаче сузить диапазон применяемых технологий ровно настолько, чтобы решить вашу задачу. Не больше не меньше. К примеру, если ID-это монотонная последовательность, с известным стартовым значением, то её можно отображать в вектор (дек или очередь) физических адресов (С++) или номеров Объектов (Java/C#) в векторе. Если стоит задача просто проверять СУЩЕСТВОВАНИЕ объекта (ключа), то можно использовать битовую карту и т.п. Не забывайте также о побочных эффетках capacity. Если вовремя не ликвидируете процессы реорганизации хеша "на ходу" то вместо константного отклика рискуете получить таймауты порядка нескольких секунд со 100% оверхедом по CPU. Есть повод заглянуть в сторону B+Tree если для вас важно отсутствие таких артефактов. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.01.2011, 16:32 |
|
||
|
не могу разобраться в смысле хеширования
|
|||
|---|---|---|---|
|
#18+
testing22и, как я понял, смысл в том, что функция хеширования позволяет иметь константное время поиска, Функция хеширования - функция, которая более-менее равномерно "размазывает" различные наборы входных данных по заданному диапазону. Ярче всего смысл этого виден, если данные лежат на внешнем носителе, и "более-менее угадать" место, откуда их читать, гораздо эффективнее, нежели совершать множество обращений к диску, путешествуя по дереву. В целом же подход за счёт траты лишней памяти обеспечивает более быстрое и более стабильное время доступа к данным. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.01.2011, 17:36 |
|
||
|
|

start [/forum/topic.php?fid=16&msg=37049111&tid=1343201]: |
0ms |
get settings: |
5ms |
get forum list: |
11ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
58ms |
get topic data: |
6ms |
get forum data: |
1ms |
get page messages: |
43ms |
get tp. blocked users: |
1ms |
| others: | 210ms |
| total: | 339ms |

| 0 / 0 |
