| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Алгоритмы > Подсчет частоты слов в тексте |
| Автор: 14SatanA88 25.10.2012, 00:36 | ||||||||||
| Доброго времени суток, уважаемые программеры. Предыстория: Не так давно, исходя из утверждений одного знакомого мне человека, решил выяснить, где же быстрее всего считается частота слов в тексте. Просто интересно стало. Но так как программист я хреновый, подумал, что не лишним будет создать тему на форуме. Входные данные: У нас есть файл с текстом, содержаший только латиницу (чтобы не заморачиваться с кодировками). Выходные данные Опять же текстовый файл, содержащий пары "слово = частота" в алфавитном порядке, разделенные переводом строки. Некоторые замечания: Будем считать словом последовательность символов из диапазона [a-zA-Z] (только буквы латинского алфавита, никаких апострофов и дефисов). Регистр символов не важен. Я взял для примера оригинал "Противостояния" Стивена Кинга (~2.5 Mb). Он лежит в аттаче. Время считается только на стадии подсчетов. То есть получение текста из файла / запись результатов / сортировка хеша по ключам не важны. Смысл создания темы: Далее я приведу исходный код сабжа на нескольких ЯП и результаты тестирования на моей машине. Я прошу Вас взглянуть на код, сказать, где можно что-либо исправить, дабы ускорить его. Ну и было бы превосходно сопроводить замечания подробными комментариями. Некоторым может быть не интересно, и поэтому прошу не оставлять бессмысленных постов. Критика же приветствуется. С++ (среднее время = 646 ms)
Java (среднее время = 605 ms)
Perl (среднее время = 224 ms)
PHP (среднее время = 307 ms)
Python (среднее время = 1448 ms)
Файлы с исходными кодами, а так же пример входного и выходного файла в аттаче. P.S. Судите строго. |
| Автор: Akina 25.10.2012, 07:35 |
| Аттача-то и не подвезли... небось не заархивировал, прежде чем аттачить? |
| Автор: disputant 25.10.2012, 08:45 |
| Не силен в остальных языках, на код C++ оставил впечатление "зачем просто, если можно сложно?!" |
| Автор: Silent 25.10.2012, 15:45 | ||||||
| Сильно возмутился я представленным цифрам, и решил проверить на деле - "за державу обидно" (за С++ то есть). Каким компилятором получен результат? учитывая присутствующий заголовочный файл <dos> и тег C++ Builder - предполагаю, что в сильно бородатом borland c++ 3.1, так? Ужас =) Вот мои результаты (среднее время по пяти замерам):
Размер тестового файла был 2,5Мб. Платформа i3, 2Gb, debian 6 (WinXP для C#) на Java решение не тестил, но мое мнение - она не должна выйти за 300-350мс, все решения тестировались "как есть" Прилагаю исходники на C# и Golang:
Golang:
|
| Автор: maxim1000 25.10.2012, 15:57 |
| ещё стоит проверить, одинаковые ли алгоритмы если Perl, например, использует хеш-контейнер, имеет смысл его использовать во всех языках |
| Автор: disputant 25.10.2012, 16:51 | ||
| Приведенный исходник C# - 172 тика. C++ с исправленными ошибками - 130 тиков. (Visual Studio 2010) Но если отказаться от string'ов и этой жуткой проверки, то примерно 89 тиков
Как я понимаю, если задача получить именно список слов с частотами, а не конкретно map, то можно и еще ускориться... P.S. В 3.1 STL еще не было |
| Автор: _Y_ 26.10.2012, 15:46 |
| 14SatanA88, подумал попробовать, но не нашел файла данных, т.е. самого текста. Где он лежит? |
| Автор: disputant 26.10.2012, 15:51 | ||
Ну, я, например, взял http://webreading.ru/conv/do_txt.php?name=/books/sf_/sf/king_stephen_the_stand |
| Автор: 14SatanA88 26.10.2012, 16:39 | ||||||
аттач подвез. там исходные коды всего что я понаписал, выходной и выходной файлы
В почти таком же бородатом Borland c++ 5.02 (кстати, посоветуйте компилятор под Windows) наверное, стоит сказать, на какой машине проверялись коды: i7, 6Gb, Win7
на самом деле здесь важна скорость работы алгоритма. то есть используем любые средства языка, лишь бы добиться максимальных показателей скорости disputant, Вам отдельное спасибо за приведенный пример. Было бы превосходно, если бы Вы вкратце написали суть алгоритма. И о map я считал, что в данной задаче это идеальный вариант. |
| Автор: disputant 27.10.2012, 07:10 | ||
Суть алгоритма - раз мы все равно втянули весь текст в память, зачем его копировать? Сразу весь преобразовали в нижний регистр, и пошли сканировать в нем слова, обрезая их (все равно между словами что-то есть, что можно безболезненно превратить в 0), так что каждое слово просто представлено указателем на место в памяти. map хранит эти указатели, но сравнивает их между собой лексикографически, как строки. Как минимум избавляемся от массы накладных расходов string. С заменой map сильно не думал, но можно попробовать взять что-то не такое универсальное, но быстрое - например, какую-нибудь хэш-таблицу, или, например, матрицу 26x27 по первым двум буквам, а в ней какие-то списки или еще что - все-таки слова обычно достаточно короткие... В общем, тут уже надо поэкспериментировать. Первый напрашивающийся вариант - собрать все в один вектор и отсортировать - из-за большого количества повторений может и не обогнать map (так что для разных текстов могут быть оптимальны разные варианты). |
| Автор: volatile 28.10.2012, 00:29 |
Ха, да уж, как это С++ на последнем месте оказался? (хотя если постараться, все можно.) Спасибо disputant, поддержал державу. Язык С++, тем и хорош, что можно ускоряться бесконечно. |
| Автор: 14SatanA88 28.10.2012, 21:11 |
| Спасибо за ответы касательно Си. Хотелось бы еще увидеть что-то относительно других ЯП. |
| Автор: 14SatanA88 29.10.2012, 13:24 | ||
volatile, премного благодарен Вам за проделанную работу. Если Вы еще под настроение напишете свой хеш, с блэкджеком и плюшками, будет вообще круто.
я чего завел вообще тему. предмет разговора был в том, что якобы java быстрее всего сделает сабж. я же предположил что perl будет быстрее (честно признаюсь, на момет разговора вообще perl знал только по работе с regexp). ну и потом мне стало интересно, и я понаписал то что смог P.S. Еще вернусь к тому, о чем спрашивал: посоветуйте компилятор для C++ под Win7 |