Проблема с нахождением простых чисел, больших 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]
Используйте другой алгоритм или рассмотрите возможность использования существующего пакета для простых чисел.