OberonCore https://forum.oberoncore.ru/ |
|
Решето Эратосфена. https://forum.oberoncore.ru/viewtopic.php?f=72&t=1964 |
Страница 1 из 2 |
Автор: | Alexey Veselovsky [ Понедельник, 19 Октябрь, 2009 18:57 ] |
Заголовок сообщения: | Решето Эратосфена. |
А есть ли быстрые реализации оного решета на Haskell'e? А то то, что я сотворил ни в какие ворота не лезло в плане производительности. |
Автор: | Geniepro [ Вторник, 20 Октябрь, 2009 08:08 ] |
Заголовок сообщения: | Re: Решето Эратосфена. |
Когда-то я баловался с этим делом, примерно такие результаты получил: Код: 100000 1000000 Haskell 1.82 sec 47.7 sec C GCC 3.4.5 0.44 sec 11.3 sec ComponentPascal 0.65 sec 17.0 sec Код: primes'wheel :: [Int] primes'wheel = 2:3:5:7:filter isPrime'wheel (spin wheel2357 11) where isPrime'wheel :: Int -> Bool isPrime'wheel !x = all (\p -> x `mod` p /= 0) $ takeWhile (\p -> p*p <= x) $ tail primes'wheel wheel2357 :: [Int] wheel2357 = 2:4:2:4:6:2:6:4:2:4:6:6:2:6:4:2:6:4:6:8:4:2:4:2: 4:8:6:4:6:2:4:6:2:6:6:4:2:4:6:2:6:4:2:4:2:10:2:10:wheel2357 spin :: [Int] -> Int -> [Int] spin (x:xs) n = n:spin xs (n + x) Код: #define maxn 1000000 int ps[maxn]; int primes_c (int n) { int i = 2, j, p = 5, f; ps[0] = 2; ps[1] = 3; while (i < n) { f = 1; j = 1; while (f && (ps[j]*ps[j] <= p)) { f = (p % ps[j]); j++; } if (f) { ps[i] = p; i++; } p += 2; } return ps[i-1]; } Код: MODULE Primes;
IMPORT SL:=StdLog; CONST nmax = 1000000; VAR ps : ARRAY nmax OF INTEGER; PROCEDURE Prime(n : INTEGER) : INTEGER; VAR i, j, p : INTEGER; f : BOOLEAN; BEGIN ps[0] := 2; ps[1] := 3; i := 2; p := 5; WHILE i < n DO f := TRUE; j := 1; WHILE f & (ps[j]*ps[j] <= p) DO f := (p MOD ps[j]) # 0; INC(j) END; IF f THEN ps[i] := p; INC(i) END; INC(p,2) END; RETURN ps[n-1] END Prime; PROCEDURE Do*; BEGIN SL.Int(Prime(1000000)); SL.Ln; END Do; END Primes. |
Автор: | Geniepro [ Вторник, 20 Октябрь, 2009 08:11 ] |
Заголовок сообщения: | Re: Решето Эратосфена. |
А вот версия, которая всего на 8% медленнее лучшей сишной: Код: {-# OPTIONS -O2 -optc-O -fbang-patterns #-}
-- -- The Computer Language Shootout -- http://shootout.alioth.debian.org/ -- -- Contributed by Don Stewart -- nsieve over an ST monad Bool array -- import Control.Monad.ST import Data.Array.ST import Data.Array.Base import System import Control.Monad import Data.Bits import Text.Printf main = do n <- getArgs >>= readIO . head :: IO Int mapM_ (sieve . (10000 *) . (2 ^)) [n, n-1, n-2] sieve n = do let r = runST (do a <- newArray (2,n) True :: ST s (STUArray s Int Bool) go a n 2 0) printf "Primes up to %8d %8d\n" (n::Int) (r::Int) :: IO () go !a !m !n !c | n == m = return c | otherwise = do e <- unsafeRead a n if e then let loop !j | j < m = do x <- unsafeRead a j when x $ unsafeWrite a j False loop (j+n) | otherwise = go a m (n+1) (c+1) in loop (n `shiftL` 1) else go a m (n+1) c |
Автор: | Илья Ермаков [ Вторник, 20 Октябрь, 2009 08:21 ] |
Заголовок сообщения: | Re: Решето Эратосфена. |
Хм, занятно-подозрительное название unsafeRead Какой-то прямой доступ к данным в памяти? |
Автор: | Info21 [ Вторник, 20 Октябрь, 2009 08:31 ] |
Заголовок сообщения: | Re: Решето Эратосфена. |
Не умеет программировать человек. |
Автор: | Geniepro [ Вторник, 20 Октябрь, 2009 08:53 ] |
Заголовок сообщения: | Re: Решето Эратосфена. |
Илья Ермаков писал(а): Хм, занятно-подозрительное название unsafeRead Какой-то прямой доступ к данным в памяти? Это вообще недокументированная функция, как и unsafeWrite. В них нет проверки индекса, которую делают документированные версии перед их вызовом этих низкоуровневых. То есть в данном случае максимальное приближение к Си. |
Автор: | Geniepro [ Вторник, 20 Октябрь, 2009 08:54 ] |
Заголовок сообщения: | Re: Решето Эратосфена. |
Info21 писал(а): Не умеет программировать человек. Кто именно? Можете привести вариант получше? |
Автор: | vvp [ Вторник, 20 Октябрь, 2009 10:51 ] |
Заголовок сообщения: | Re: Решето Эратосфена. |
Geniepro писал(а): Info21 писал(а): Не умеет программировать человек. Кто именно? Можете привести вариант получше? Эратосфен придумал свой алгоритм для того, чтобы избавиться от операций деления и умножения в любом виде. То есть от нахождения остатка тоже надо избавлятся. Там достаточно операций счета количества пройденных чисел. Сейчас кстати у меян идет занятия и на соседней машине мальчишка 9-классник завершает решето без делений. Это не в обиду сказано. Просто использование операций деления в решете достаточно типичная ошибка. Это я не как программист, это я как учитель. |
Автор: | Info21 [ Вторник, 20 Октябрь, 2009 11:05 ] |
Заголовок сообщения: | Re: Решето Эратосфена. |
vvp писал(а): Просто использование операций деления в решете достаточно типичная ошибка. Как и неумение писать циклы.
|
Автор: | Alexey Veselovsky [ Вторник, 20 Октябрь, 2009 11:07 ] |
Заголовок сообщения: | Re: Решето Эратосфена. |
Geniepro писал(а): Info21 писал(а): Не умеет программировать человек. Кто именно? Можете привести вариант получше? Вот вариант накиданый по быстрому по описанию с википедии (http://ru.wikipedia.org/wiki/Решето_Эратосфена): Код: #include <iostream> #include <vector> int main () { int n = 0; std::cin >> n; std::vector<bool> prime (n); for (int i=2; i<n; ++i) prime[i]=true; for (int i=2; (i*i)<=n; ++i) { if (prime[i]) for (int j=(i*i); j<=n; j+=i) prime[j]=false; } for (int i=0; i<n; ++i) if (prime[i]) std::cout << " " << i; std::cout << std::endl; return 0; } Миллион считает сильно быстрее чем за секунду. PS. Да, первые два элемента в векторе лишние. И да, можно было написать чуть красивей. |
Автор: | Geniepro [ Вторник, 20 Октябрь, 2009 11:17 ] |
Заголовок сообщения: | Re: Решето Эратосфена. |
vvp писал(а): Эратосфен придумал свой алгоритм для того, чтобы избавиться от операций деления и умножения в любом виде. То есть от нахождения остатка тоже надо избавлятся. Ну значит у меня не решето Эратосфена вышло...
|
Автор: | Geniepro [ Вторник, 20 Октябрь, 2009 11:18 ] |
Заголовок сообщения: | Re: Решето Эратосфена. |
Info21 писал(а): Как и неумение писать циклы. Ну а в циклах-то где проблема? |
Автор: | Geniepro [ Вторник, 20 Октябрь, 2009 11:20 ] |
Заголовок сообщения: | Re: Решето Эратосфена. |
Alexey Veselovsky писал(а): А то то, что я сотворил ни в какие ворота не лезло в плане производительности. А что Вы сотворили-то? |
Автор: | Илья Ермаков [ Вторник, 20 Октябрь, 2009 11:22 ] |
Заголовок сообщения: | Re: Решето Эратосфена. |
Если в цикле возникает "f: BOOLEAN" - флаг в условии, то это значит, что цикл составлен неверно. Эмуляция break через логический флаг. (Излюбленное возражение самоделкиных - "а если я буду без брейков, то мне нужны логические флаги.."). |
Автор: | Geniepro [ Вторник, 20 Октябрь, 2009 11:42 ] |
Заголовок сообщения: | Re: Решето Эратосфена. |
Илья Ермаков писал(а): Если в цикле возникает "f: BOOLEAN" - флаг в условии, то это значит, что цикл составлен неверно. Эмуляция break через логический флаг. Вы имеете в виду этот кусок: Код: f := TRUE; Да, помню это место. Вначале так не было, приходилось дважды вычислять выражение (p MOD ps[j]) # 0, а так как оптимизатора в компиляторе BB нет, то это замедляло выполнение на 20%. Так что это просто оптимизация.j := 1; WHILE f & (ps[j]*ps[j] <= p) DO f := (p MOD ps[j]) # 0; INC(j) END; IF f THEN ps[i] := p; INC(i) END; А вы тут сразу -- "не умеешь, не умеешь!!!" |
Автор: | Илья Ермаков [ Вторник, 20 Октябрь, 2009 11:59 ] |
Заголовок сообщения: | Re: Решето Эратосфена. |
Ну да, правда. |
Автор: | Alexey Veselovsky [ Вторник, 20 Октябрь, 2009 14:52 ] |
Заголовок сообщения: | Re: Решето Эратосфена. |
Geniepro писал(а): Alexey Veselovsky писал(а): А то то, что я сотворил ни в какие ворота не лезло в плане производительности. А что Вы сотворили-то? Вот такой вот ужоз: Код: prime' n = loop1 (listArray (2,n) (repeat True)) 2 n
where loop1 arr i n | (i*i)>n = arr loop1 arr i n | (arr ! i)= loop1 (loop2 arr (i*i) i n) (i+1) n loop1 arr i n = loop1 arr (i+1) n loop2 arr j i n | j<=n = loop2 (arr//[(j,False)]) (j+i) i n loop2 arr j i n = arr main = do s <- getLine cout (prime' $ read s) 2 (read s) cout :: Array Int Bool -> Int -> Int -> IO () cout arr i n | i<=n && (arr ! i) = do print i cout arr (i+1) n cout arr i n | i<=n = cout arr (i+1) n cout arr i n = print "--" |
Автор: | Geniepro [ Вторник, 20 Октябрь, 2009 15:45 ] |
Заголовок сообщения: | Re: Решето Эратосфена. |
Alexey Veselovsky писал(а): Вот такой вот ужоз: Массивы Array в GHC жутко тормозные, я это тоже замечал... |
Автор: | Alexey Veselovsky [ Вторник, 20 Октябрь, 2009 15:46 ] |
Заголовок сообщения: | Re: Решето Эратосфена. |
Geniepro писал(а): Alexey Veselovsky писал(а): Вот такой вот ужоз: Массивы Array в GHC жутко тормозные, я это тоже замечал... Не думаю, что если этот же пример собрать каким-нибудь UHC, программа станет работать существенно быстрее |
Автор: | Geniepro [ Вторник, 20 Октябрь, 2009 15:53 ] |
Заголовок сообщения: | Re: Решето Эратосфена. |
А попробуйте STUArray как в том примере с shootout -- может получше будет? |
Страница 1 из 2 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |