我正在研究一个程序,用指数2得到最接近的素数,这是在一个区间之间。
module Main where
import Data.Char
import System.IO
import Control.Monad (liftM)
data PGetal = G Bool | P Int
instance Show PGetal where
show (P n) = show n
show (G False) = "GEEN PRIEMGETAL GEVONDEN"
mPriem::(Int, Int) -> PGetal
mPriem (x,y) | (x > y) = G False
| (x > 1000000) = G False
| (y > 1000000) = G False
| (null (getAllPriem(x,y))) = G False
| otherwise = P (kleinsteVerschilF(getAllPriem(x,y),1000000,1))
kleinsteVerschilF:: ([Int], Int , Int) -> Int
kleinsteVerschilF ([],_, priemGetal) = priemGetal
kleinsteVerschilF (priem1:priemcss, kleinsteVerschil,priemGetal)=
if(kleinsteVerschil <= kleinsteVerschilMetLijst (priem1,(getMachtenVanTwee(0)),1000000))then kleinsteVerschilF(priemcss, kleinsteVerschil,priemGetal)
else kleinsteVerschilF (priemcss,kleinsteVerschilMetLijst(priem1,(getMachtenVanTwee(0)),1000000), priem1)
kleinsteVerschilMetLijst :: (Int,[Int],Int) -> Int
kleinsteVerschilMetLijst ( _,[],kleinsteVerschil) = kleinsteVerschil
kleinsteVerschilMetLijst (x,tweeMachten1:tweeMachtencss,kleinsteverschil)=
if((abs(x-tweeMachten1)) < kleinsteverschil)
then kleinsteVerschilMetLijst(x,tweeMachtencss, (abs(x-tweeMachten1)))
else kleinsteVerschilMetLijst(x,tweeMachtencss, kleinsteverschil)
getAllPriem :: (Int, Int) ->[Int]
getAllPriem (x,y) = filter isPriem [x..y]
getMachtenVanTwee ::(Int) -> [Int]
getMachtenVanTwee (macht)
|(functieMachtTwee(macht)< 1000000) = (functieMachtTwee(macht)) : (getMachtenVanTwee ((macht+1)))
| otherwise = []
functieMachtTwee:: (Int) -> Int
functieMachtTwee (x) = 2^x
isPriem n = (aantalDelers n)==2
aantalDelers n = telAantalDelersVanaf n 1
telAantalDelersVanaf n kandidaatDeler
| n == kandidaatDeler = 1
| mod n kandidaatDeler == 0
= 1 + telAantalDelersVanaf n (kandidaatDeler+1)
| otherwise
= telAantalDelersVanaf n (kandidaatDeler+1)
aantalDelers2 getal = telDelers getal 1 0
where telDelers n kandidaat teller
| n == kandidaat = 1+teller
| mod n kandidaat == 0
= telDelers n (kandidaat+1) (teller+1)
| otherwise
= telDelers n (kandidaat+1) teller
transform :: [String] -> [PGetal]
transform [] = []
transform (cs:css) =
let (a : b: _ ) = words cs
in (mPriem ((read(a)),(read(b))): transform css)
main :: IO ()
main = do
n <- read `liftM` getLine :: IO Int
lss <- lines `liftM` getContents
let cases = take n lss
let vs = (transform (lss))
putStr $ unlines $ map show vs
当我使用mPriem函数时,它工作正常。 但它需要使用输入txt文件,所以我使用ghc命令创建了一个.exe文件。我还在文件夹中添加了这个.txt文件。
10
1 1
1 3
1 100
200 250
14 16
5 10
20 31
16 50
100 120
5200 7341
当我在命令行中使用此命令时,它什么都不做。没有输出。我不能用CTRL + C来停止程序,所以我觉得它崩溃了。但我不知道出了什么问题。
type invoer.txt | programma.exe
答案 0 :(得分:2)
你的程序有效,但效率不高,而且个人觉得它不那么优雅(对不起:S),因为你引入了很多&#34;噪音&#34;。因此,在写入输出之前需要花费很多时间。
如果我正确理解问题陈述,每一行(第一行除外)都包含两个整数,你需要计算这两个数字之间的素数(包括边界?)
首先,你可以通过定义一个函数来更优雅地做到这一点:cPrime :: Int -> Int -> Int
将两个数字作为输入并返回素数的数量:
cPrime :: Int -> Int -> Int
cPrime a b = count $ filter isPrime [a .. b]
您可以通过改进主要检查算法来提高性能。首先,您不需要检查1
是否为除数,因为1
始终是除数。此外,您可以在数学上证明没有除 sqrt(n)( n 除外)的除数除以 n ;除非有另一个小于 sqrt(n)的分隔符。这意味着你可以简单地枚举2
和sqrt n
之间的所有数字,并且从其中一个是除数的那一刻起,你可以停止:你已经证明这个数字不是素数:
isPrime :: Int -> Bool
isPrime 1 = False
isPrime 2 = True
isPrime n = all ((0 /=) . mod n) (2:[3,5..m])
where m = floor $ sqrt $ fromIntegral n
现在我不确定你打算用kleinsteVerschilF
做什么。