Простые числа Хаскелла - PullRequest
       10

Простые числа Хаскелла

0 голосов
/ 06 сентября 2018

Я хочу генерировать бесконечные простые числа, но в некоторых случаях он останавливается без завершения бесконечного списка

вот моя попытка:

Primeach :: [Int]

Primeach = [n | n <- [2..] , product [1..n-1] `rem` n == n-1]

1 Ответ

0 голосов
/ 06 сентября 2018

Проблема с нахождением простых чисел, больших 19, вытекает из линии

primeach :: [Int]

Это потому, что вы должны рассчитать product [1..n-1] для этих чисел. Это переполняется, когда n >= 22, поскольку Int - это (обычно) 64-битное число под капотом в 64-битных системах (гарантированно должно быть не менее 30 бит), в 32-битных системах с 32-битной Int переполнится при n >= 14.
Поскольку он переполняется, вы больше не берете правильный остаток.
Например, для 64-битных целых чисел со знаком мы имеем для n=23 (что является простым):

Prelude> product [1..22]
1124000727777607680000 :: Integer
Prelude> product [1..22] :: Int
-1250660718674968576 :: Int
Prelude> product [1..22] `rem` 23
22 :: Integer
Prelude> product [1..22] `rem` 23 :: Int
-22 :: Int

Как видите, это больше не работает из-за переполнения. Другим примером будет n=29, который также прост:

Prelude> product [1..28]
304888344611713860501504000000 :: Integer
Prelude> product [1..28] :: Int
-5968160532966932480 :: Int
Prelude> product [1..28] `rem` 29
28 :: Integer
Prelude> product [1..28] `rem` 29 :: Int
-27 :: Int

Так что это показывает, что это даже не просто перевернуть знак.

У вас есть 2 варианта:

  • Если вы хотите использовать этот алгоритм, переключитесь на Integer s (даже если только для вычисления product), они никогда не переполнятся:

    primeach :: [Int]
    primeach = [fromInteger n | n <- [2..] , product [1..n-1] `rem` n == n-1]
    
  • Используйте другой алгоритм или рассмотрите возможность использования существующего пакета для простых чисел.

...