Perfect numbers: Difference between revisions

Content added Content deleted
(→‎traditional method: replaced with the appropriate REXX program.)
m (→‎Lucas-Lehmer + other optimizations: changed indentations in the isPerfect function.)
Line 1,858: Line 1,858:


===Lucas-Lehmer + other optimizations===
===Lucas-Lehmer + other optimizations===
This version uses the Lucas-Lehmer method, digital root, and restricts itself to even numbers, and
This version uses the Lucas-Lehmer method, digital roots, and restricts itself to   ''even''   numbers, and
<br>also utilizes a check for the last-two-digits as per François Édouard Anatole Lucas (in 1891).
<br>also utilizes a check for the last-two-digits as per François Édouard Anatole Lucas (in 1891).


Line 1,882: Line 1,882:
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
isPerfect: procedure expose @. !. ? /*expose (make global) some variables. */
isPerfect: procedure expose @. !. ? /*expose (make global) some variables. */
parse arg x 1 y '' -2 ? /*# (and copy), and the last 2 digits.*/
parse arg x 1 y '' -2 ? /*# (and copy), and the last 2 digits.*/
if x==6 then return 1 /*handle the special case of six. */
if x==6 then return 1 /*handle the special case of six. */
if !.?==2 then return 0 /*test last two digits: François Lucas.*/
if !.?==2 then return 0 /*test last two digits: François Lucas.*/
/*╔═════════════════════════════════════════════╗
/*╔════════════════════════════════════════════════════════════════════════════════════╗
║ Lucas─Lehmer know that perfect numbers can ║
║ Lucas─Lehmer know that perfect numbers can be expressed as: [2^n -1] * {2^(n-1) } ║
║ be expressed as: [2^n -1] * {2^(n-1) } ║
╚════════════════════════════════════════════════════════════════════════════════════╝*/
╚═════════════════════════════════════════════╝*/
if @.0<x then do @.1=@.1 while @._ <= x; _=(2**@.1-1)*2**(@.1-1); @.0=_; @._=_
end /*@.1*/ /* [↑] uses memoization for formula. */
if @.0<x then do @.1=@.1 while @._<=x; _=(2**@.1-1)*2**(@.1-1); @.0=_; @._=_
end /*@.1*/ /* [↑] uses memoization for formula. */


if @.x==0 then return 0 /*Didn't pass Lucas-Lehmer? Not perfect*/
if @.x==0 then return 0 /*Didn't pass Lucas-Lehmer? Not perfect*/
/*[↓] perfect numbers digital root = 1*/
/*[↓] perfect numbers digital root = 1*/
do until y<10 /*find the digital root of Y. */
do until y<10 /*find the digital root of Y. */
parse var y d 2; do k=2 for length(y)-1; d=d+substr(y,k,1); end /*k*/
parse var y d 2; do k=2 for length(y)-1; d=d+substr(y,k,1); end /*k*/
y=d /*find digital root of the digital root*/
y=d /*find digital root of the digital root*/
end /*until*/ /*wash, rinse, repeat ··· */
end /*until*/ /*wash, rinse, repeat ··· */


if d\==1 then return 0 /*Is digital root ¬ 1? Then ¬ perfect.*/
if d\==1 then return 0 /*Is digital root ¬ 1? Then ¬ perfect.*/
s=3 + x%2 /*we know the following factors: unity,*/
s=3 + x%2 /*we know the following factors: unity,*/
z=x /*2, and x÷2 (x is even). _____*/
z=x /*2, and x÷2 (x is even). */
q=1; do while q<=z; q=q*4; end /*while q≤z*/ /* [↓] R will be the integer X */
q=1; do while q<=z; q=q*4 ; end /*while q≤z*/ /* _____*/
r=0 /* [↓] R will be the integer √ X */
r=0
do while q>1; q=q%4; _=z-r-q; r=r%2; if _>=0 then do; z=_; r=r+q; end
do while q>1; q=q%4; _=z-r-q; r=r%2; if _>=0 then do; z=_; r=r+q; end
end /*while q>1*/ /* [↑] compute the integer SQRT of X.*/
end /*while q>1*/ /* [↑] compute the integer SQRT of X.*/
/* ___ */
/* _____*/
do j=3 to r until s>x /*starting at 3, find factors ≤ √ X */
do j=3 to r until s>x /*starting at 3, find factors ≤ √ X */
if x//j==0 then s=s+j+x%j /*J divisible by X? Then add J and X÷J*/
if x//j==0 then s=s+j+x%j /*J divisible by X? Then add J and X÷J*/
end /*j*/
end /*j*/
return s==x /*if the sum matches X, then perfect! */</lang>
return s==x /*if the sum matches X, then perfect! */</lang>
'''output''' &nbsp; is the same as the traditional version &nbsp; and is about &nbsp; '''500''' &nbsp; times faster &nbsp; (testing 34,000,000 numbers). <br><br>
'''output''' &nbsp; is the same as the traditional version &nbsp; and is about &nbsp; '''500''' &nbsp; times faster &nbsp; (testing 34,000,000 numbers). <br><br>