Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: уникальный хеш из двух чисел

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Без описания
OrmaJever Модератор
Отправлено: 25 Октября, 2014 - 21:14:45
Post Id



Активный участник


Покинул форум
Сообщений всего: 7540
Дата рег-ции: Янв. 2010  
Откуда: Чернигов


Помог: 299 раз(а)




Задача на миллион! Есть 2 любые числа, нужно получить такое число (хеш) что бы оно было уникальным для любой пары, но не зависело от расположения этих чисел. Например
есть 2 числа 1 и 2, нужна формула по который для 1 и 2 будет такой же хеш как и для 2 и 1, но уникальный для другой пары.
То есть
1 * 2 = 2
2 * 1 = 2
но в этой формуле слишком много колизий, например 2*10 = 20 5*4 тоже = 20, а нужны уникальные значения для каждой пары.
Простой код для проверки коллизий
PHP:
скопировать код в буфер обмена
  1. $arr = array();
  2. for( $y=1; $y<50; ++$y) {
  3.     for( $x = 1; $x<50; ++$x) {
  4.         $arr[] = ($y / $x) + ($x / $y); // формула
  5.     }
  6. }
  7. sort($arr);
  8. var_dump(count($arr) == count(array_unique($arr)));
  9. var_dump($arr)


-----
Если вы хотя бы 3-4 раза не решите всё выкинуть и начать заново - вы явно что-то делаете не так.
 
 Top
dcc0
Отправлено: 25 Октября, 2014 - 21:50:11
Post Id


Участник


Покинул форум
Сообщений всего: 1043
Дата рег-ции: Июль 2014  


Помог: 10 раз(а)




А нельзя так? Генерировать хе ш для 1 затем для 2
Собирать в одно число, обрезать каждый хеш, соединять в один из двух кусков, при этом ввести правило, что в самом алгоритме, допустим, меньшее всегда предшествует большему. Т.е. числа упорядочиваютя до операции хешерования.

(Отредактировано автором: 25 Октября, 2014 - 21:51:55)



-----
Март 2021. Бросил программирование
 
 Top
OrmaJever Модератор
Отправлено: 25 Октября, 2014 - 22:03:55
Post Id



Активный участник


Покинул форум
Сообщений всего: 7540
Дата рег-ции: Янв. 2010  
Откуда: Чернигов


Помог: 299 раз(а)




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


-----
Если вы хотя бы 3-4 раза не решите всё выкинуть и начать заново - вы явно что-то делаете не так.
 
 Top
Мелкий Супермодератор
Отправлено: 25 Октября, 2014 - 22:12:25
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




xor?


-----
PostgreSQL DBA
 
 Top
OrmaJever Модератор
Отправлено: 25 Октября, 2014 - 22:19:34
Post Id



Активный участник


Покинул форум
Сообщений всего: 7540
Дата рег-ции: Янв. 2010  
Откуда: Чернигов


Помог: 299 раз(а)




Мелкий, а что xor? сам по себе он возвращает bool, а битовый ^ даёт очень много повторений
(Добавление)
Вот более правильный скрипт проверки колизий
PHP:
скопировать код в буфер обмена
  1. $arr = array();
  2. for( $y=1; $y<100; ++$y) {
  3.     for( $x = 1; $x<100; ++$x) {
  4.         if( $x == $y ) continue;
  5.         $arr[] = $y / $x + $x / $y; // <- формула
  6.     }
  7. }
  8. asort($arr);
  9. $count = count($arr);
  10. $coll = $count - count(arraY_unique($arr));
  11. echo round($coll * 100 / $count, 1), '% коллизий';


-----
Если вы хотя бы 3-4 раза не решите всё выкинуть и начать заново - вы явно что-то делаете не так.
 
 Top
OrmaJever Модератор
Отправлено: 26 Октября, 2014 - 10:31:25
Post Id



Активный участник


Покинул форум
Сообщений всего: 7540
Дата рег-ции: Янв. 2010  
Откуда: Чернигов


Помог: 299 раз(а)




ладно, раз в предложениями туго тогда опишу идея по другому.
Есть таблица сообщений в бд с полями from_id (от кого) и to_id (кому)
Дак вот, все эти сообщения нужно групировать и выводить в виде беседы, то есть
from_id = 5 AND to_id = 10
это одна беседа с
from_id = 10 AND to_id = 5
То есть мне для вывода списка бесед нужно сгрупировать по этим двум полям, но как если они могут быть в разной последовательности?
Вариант создать другую таблицу "conversation" где будет id беседы - не предлагать Улыбка
Я могу создать отдельное поле в котором хранить id или хеш беседы, но как его генерировать?


-----
Если вы хотя бы 3-4 раза не решите всё выкинуть и начать заново - вы явно что-то делаете не так.
 
 Top
Мелкий Супермодератор
Отправлено: 26 Октября, 2014 - 11:08:35
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




Я-то думал задача сугубо математическая.

Берёте поле в 2 раза превышающее по размеру from_id и to_id, bigint, видимо, и пишете туда (для 64-битной версии PHP, для 32-битной лучше со строками и str_pad сделать):
PHP:
скопировать код в буфер обмена
  1. $iMaxDigitsCount = 10; // я не помню, сколько десятичных знаков в int'е.
  2. if ($x > $y) $hash = $x*pow(10, $iMaxDigitsCount) + $y;
  3. else $hash = $y*pow(10, $iMaxDigitsCount) + $x;


-----
PostgreSQL DBA
 
 Top
OrmaJever Модератор
Отправлено: 26 Октября, 2014 - 11:19:41
Post Id



Активный участник


Покинул форум
Сообщений всего: 7540
Дата рег-ции: Янв. 2010  
Откуда: Чернигов


Помог: 299 раз(а)




тут как оказалось - "а слона то я и не заметил". Я изначально хотел сугубо математическое решение что бы делать его прямо в запросе аля
CODE (SQL):
скопировать код в буфер обмена
  1. GROUP BY (from_id + to_id)

но сейчас вот подумал, я ведь могу в php сортировать from_id и to_id от меньшего до большего и делать из них хеш который буду записывать в отдельное поле. Это же банально просто Растерялся


-----
Если вы хотя бы 3-4 раза не решите всё выкинуть и начать заново - вы явно что-то делаете не так.
 
 Top
Мелкий Супермодератор
Отправлено: 26 Октября, 2014 - 11:31:26
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




Можно и на sql, if есть, возведение в степень тоже.
CODE (SQL):
скопировать код в буфер обмена
  1. GROUP BY IF (from_id>to_id, from_id*pow(10,10)+to_id, to_id*pow(10,10)+from_id)

Операторами бинарного сдвига будет компактнее, да только я их не помню Закатив глазки


-----
PostgreSQL DBA
 
 Top
OrmaJever Модератор
Отправлено: 26 Октября, 2014 - 13:03:38
Post Id



Активный участник


Покинул форум
Сообщений всего: 7540
Дата рег-ции: Янв. 2010  
Откуда: Чернигов


Помог: 299 раз(а)




так, окей, это работает! Но теперь главный вопрос, насколько эти вычисления в group by ресурсоёмкие? Может всё такие лучше создать отдельное поле и результат вот этих вычислений (на php) записывать туда и группировать по уже готовому результату?


-----
Если вы хотя бы 3-4 раза не решите всё выкинуть и начать заново - вы явно что-то делаете не так.
 
 Top
snikers987
Отправлено: 26 Октября, 2014 - 13:26:27
Post Id



Участник


Покинул форум
Сообщений всего: 1239
Дата рег-ции: Сент. 2011  
Откуда: Крым


Помог: 25 раз(а)




Может я чего то не понял, а что мешает взять 2 числа и конкатенировать их, предварительно отсортировав, например по формуле, $min_id.$max_id ?

Для
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. from_id = 5 AND to_id = 10
  3. from_id = 10 AND to_id = 5
  4.  


хеш будет 510.

Псевдокод:
PHP:
скопировать код в буфер обмена
  1.  
  2. $ids = array($from_id, $to_id);
  3. sort($ids);
  4. echo $hash = join('', $ids);
  5.  


Такой вариант будет правильно работать и в случае, если в беседе более 2 участников.

Можно прямо в SQL:
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. GROUP BY IF(from_id>to_id, CONCAT(to_id, from_id), CONCAT(from_id, to_id))
  3.  

(Отредактировано автором: 26 Октября, 2014 - 13:35:48)



-----
Когда всматриваешься в тёмную бездну, учти, что кто-то может смотреть на тебя из неё...
 
My status
 Top
OrmaJever Модератор
Отправлено: 26 Октября, 2014 - 14:05:29
Post Id



Активный участник


Покинул форум
Сообщений всего: 7540
Дата рег-ции: Янв. 2010  
Откуда: Чернигов


Помог: 299 раз(а)




snikers987 пишет:
а что мешает взять 2 числа и конкатенировать их

по сути ничего, только нужно добавить сепаратор потому что 311 и 415 совпадёт с 31 и 1415, и тут уже вопрос в производительности, мне кажется что математически операции быстрее чем обьединение строк
(Добавление)
В общем решено, отдельное поле с индефикатором переписки в любом случае нужно создавать, что бы потом его в ссылку писать для отображения самой переписки. В каком формате делать уже по ходу решу.


-----
Если вы хотя бы 3-4 раза не решите всё выкинуть и начать заново - вы явно что-то делаете не так.
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Вопросы новичков »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB