Scheme 球拍编程。我哪里做错了?

Scheme 球拍编程。我哪里做错了?,scheme,racket,primes,prime-factoring,Scheme,Racket,Primes,Prime Factoring,我想回答的问题是: 13195的主要因子为5、7、13和29。 数字600851475143中最大的素因子是什么 我哪里做错了?我的青春?测试似乎是个问题,但它在相对较小的数字上运行良好。然而,最重要的是什么?这个测试给出了一个大数字的错误答案。有没有更简单的方法 (定义B3) (定义z 0) (界定分歧? (lambda(a-b) (=(余数a b)0))) (定义(素数?n) (续) ((或(=n1)(=n0))假) ((偶数?n)假) (=n2)正确) (=nb)正确) ((b)假) (e

我想回答的问题是:
13195的主要因子为5、7、13和29。 数字600851475143中最大的素因子是什么

我哪里做错了?我的青春?测试似乎是个问题,但它在相对较小的数字上运行良好。然而,最重要的是什么?这个测试给出了一个大数字的错误答案。有没有更简单的方法

(定义B3)
(定义z 0)
(界定分歧?
(lambda(a-b)
(=(余数a b)0)))
(定义(素数?n)
(续)
((或(=n1)(=n0))假)
((偶数?n)假)
(=n2)正确)
(=nb)正确)
((b)假)
(else(and(set!b(+b1))(素数n()()))
;最大素因子检验
(定义(LPF x)
(续)
((除以?600851475143 x)
(续)
((素数?x)
(续)
((>xz)(集合!zx()()())))
(如果(
简单答案:

$ factor 600851475143
600851475143: 71 839 1471 6857
更严肃的回答:你的
prime?
函数确实坏了;我甚至不知道它想做什么。(另外,您的
(=n2)
测试太晚了,没有用处:
(偶数?n)
测试已经胜过了它。)

我的建议是:实施该计划。以下是。

简单的答案:

$ factor 600851475143
600851475143: 71 839 1471 6857
更严肃的回答:你的
prime?
函数确实坏了;我甚至不知道它想做什么。(另外,您的
(=n2)
测试太晚了,没有用处:
(偶数?n)
测试已经胜过了它。)


我的建议是:实施该计划。以下是。

用某种伪代码编写,您的意图似乎是

 pe3 = last [x | x <- [2 .. 775146], isPrime x, rem 600851475143 x == 0]
此算法可能适用于所涉及的特定数字,但不幸的是,它通常是不正确的-例如对于9000009,其整数平方根为3000,它将返回101。但9901是正确的答案(即9901是9000009的最大素数因子,而不是101)

让我们首先关注寻找最小的素因子,而不是:

pe3a n = head ([x | x <- [2 .. isqrt n], rem n x == 0, isPrime x] ++ [n])
现在我们可以从我们的数字中除以3:

> div 9000009 3 
3000003
继续3000003,而不是9000009。这意味着我们可以停在它的平方根1732处,而不是3000处——这是一个相当大的效率提升!此外,我们不需要从2开始-它已经过测试-我们可以从最后发现的因素开始:

pe3b (start, n) = (d, div n d)
  where
     d = head ([x | x <- [start .. isqrt n], rem n x == 0, isPrime x] ++ [n])

> pe3b (3, 3000003)
(3,1000001)
找到的下一个素因子是101,现在要分解的数是1000001/101=9901。我们再次从最后找到的除数101开始,因为所有较小的除数都已经尝试过了:

> pe3b (101, 9901)
(9901,1)
有趣
isqrt(9901)=99
,列表
[101..99]
为空,因此立即生成结果。9901是第一个超过100的因子,事实上是超过1的因子,因为之前的所有数字都已经连续尝试过了,并从中分离出来。这意味着9901是素数,不需要测试它的素数

事实上,通过相同的推理,该算法找到的所有因子都可以通过构造保证为素数,并且对
isPrime
的所有调用都是多余的

还要注意,这里执行除法(余数运算)的最大数字是101,而不是3000。我们的新算法不仅正确,而且效率更高

现在,您可以在重复的
pe3b
应用程序的方案中编码,并除以最后找到的因子。到达1时停止


那么在

divStep(开始,n)=(d,div n d)
其中d=head([x | x 1).fst).drop 1.迭代divStep$(2,n)
因子n=映射fst.因子分解$n
iPrime n=因子n==[n]
$
读为“of”。
直到
pred step start是函数重复应用的高阶模式,直到满足谓词(
(==1)。snd)
表示结果的第二个分量等于1)。它通常用命名为
let
的模式进行编码

要查看整个计算历史,
iterate
step start是另一种模式,它收集所有中间结果(以及起始值,我们不需要它,所以我们
删除它)。为了只查看因子本身,我们使用
map fst
获取每个结果的第一个分量。如果一个数字本身是唯一大于1的除数,则该数字为素数。测试:

pe3 900009 9901 >因子分解900009 [(3,3000003),(3,1000001),(101,9901),(9901,1)] >因子900009 [3,3,101,9901] >pe3 600851475143 6857 >因子分解600851475143 [(718462696833),(83910086647),(14716857),(6857,1)]--1471是最大的 >因子600851475143——因子试验, [7183914716857]——*不是*775146!! >系数60085147514399917——isqrt 60085147514399917==775146099 [4137309392798360393]——isqrt 392798360393==626736
用某种伪代码编写,您的意图似乎是

 pe3 = last [x | x <- [2 .. 775146], isPrime x, rem 600851475143 x == 0]
此算法可能适用于所涉及的特定数字,但不幸的是,它通常是不正确的-例如对于9000009,其整数平方根为3000,它将返回101。但9901是正确答案(即9901是9000009的最大素因子,而不是101)

让我们首先关注寻找最小的素因子,而不是:

pe3a n = head ([x | x <- [2 .. isqrt n], rem n x == 0, isPrime x] ++ [n])
现在我们可以从我们的数字中除以3:

> div 9000009 3 
3000003
继续3000003,而不是9000009。这意味着我们可以停在它的平方根1732,而不是3000-效率上的一个相当大的提高!此外,我们不需要从2开始-它已经过测试-我们可以从最后发现的因子开始:

pe3b (start, n) = (d, div n d)
  where
     d = head ([x | x <- [start .. isqrt n], rem n x == 0, isPrime x] ++ [n])

> pe3b (3, 3000003)
(3,1000001)
下一个找到的素数因子是101,现在要分解的数是1000001/101=9901。我们再次从上一个找到的因子101开始,因为所有较小的因子都已经尝试过了:

> pe3b (101, 9901)
(9901,1)
有趣。
isqrt(9901)==99
,列表
[101..99]