Totient function: Difference between revisions
m (→{{header|Pascal}}: faster totient function like on wikipedia used in GO etc..) |
|||
Line 441: | Line 441: | ||
real 3m39,745s</pre> |
real 3m39,745s</pre> |
||
===alternative=== |
|||
changing Totient-funtion in program atop to Computing Euler's totient function on wikipedia, like GO and C. |
|||
Impressive speedup, but trial division is faster for prime checking, cause it stops immediately, if not prime is sure. |
|||
<lang pascal>function totient(n:NativeUInt):NativeUInt; |
|||
var |
|||
i, quot: NativeINt; |
|||
Begin |
|||
result := n; |
|||
//i = 2 checked seperatly |
|||
//delete true dividers of n kind of 2,4,8,16 ... |
|||
while not(ODD(n)) do |
|||
Begin |
|||
n := n DIV 2; |
|||
result := result DIV 2; |
|||
end; |
|||
i := 3; |
|||
//i = 3,5,7,9,11.... |
|||
while i*i <= n do |
|||
Begin |
|||
// delete true dividers n kind of i, i², i³ ... |
|||
repeat |
|||
quot := n DIV i; |
|||
//same as if n MOD i = 0 |
|||
IF n <> quot*i then |
|||
BREAK |
|||
else |
|||
Begin |
|||
n := quot; |
|||
dec(result,result DIV i); |
|||
end; |
|||
until false; |
|||
inc(i,2); |
|||
end; |
|||
if n> 1 then |
|||
dec(result,result div n); |
|||
end; |
|||
function CheckPrimeTrial(n:NativeUint):Boolean; |
|||
var |
|||
i : NativeUint; |
|||
begin |
|||
result := ODD(n); |
|||
i := 3; |
|||
while result AND ( i*i <= n) do |
|||
Begin |
|||
result := (n mod i) <> 0; |
|||
inc(i,2); |
|||
end; |
|||
end;</lang> |
|||
;Output: |
|||
<pre> |
|||
same as above,but by far faster. |
|||
... |
|||
Limit primecount |
|||
100 25 |
|||
1000 168 |
|||
10000 1229 |
|||
100000 9592 |
|||
real 0m0,048s |
|||
.. |
|||
1000000 78498 |
|||
10000000 664579 |
|||
real 0m32,428s |
|||
</pre> |
|||
=={{header|Perl 6}}== |
=={{header|Perl 6}}== |
||
{{works with|Rakudo|2018.11}} |
{{works with|Rakudo|2018.11}} |
Revision as of 13:17, 8 December 2018
You are encouraged to solve this task according to the task description, using any language you may know.
The totient function is also known as:
- Euler's totient function
- Euler's phi totient function
- phi totient function
- Φ function (uppercase Greek phi)
- φ function (lowercase Greek phi)
- Definitions (as per number theory)
The totient function:
- counts the integers up to a given positive integer n that are relatively prime to n
- counts the integers k in the range 1 ≤ k ≤ n for which the greatest common divisor gcd(n,k) is equal to 1
- counts numbers ≤ n and prime to n
If the totient number (for N) is one less than N, then N is prime.
- Task
Create a totient function and:
- Find and display (1 per line) for the 1st 25 integers:
- the integer (the index)
- the totient number for that integer
- indicate if that integer is prime
- Find and display the count of the primes up to 100
- Find and display the count of the primes up to 1,000
- Find and display the count of the primes up to 10,000
- Find and display the count of the primes up to 100,000 (optional)
Show all output here.
- Related task
- Also see
-
- the Wikipedia entry for Euler's totient function.
- the MathWorld entry for totient function.
- the OEIS entry for Euler totient function phi(n).
C
Translation of the second Go example <lang C> /*Abhishek Ghosh, 7th December 2018*/
- include<stdio.h>
int totient(int n){ int tot = n,i;
for(i=2;i*i<=n;i+=2){ if(n%i==0){ while(n%i==0) n/=i; tot-=tot/i; }
if(i==2) i=1; }
if(n>1) tot-=tot/n;
return tot; }
int main() { int count = 0,n,tot;
printf(" n %c prime",237);
printf("\n---------------\n");
for(n=1;n<=25;n++){ tot = totient(n);
if(n-1 == tot) count++;
printf("%2d %2d %s\n", n, tot, n-1 == tot?"True":"False"); }
printf("\nNumber of primes up to %6d =%4d\n", 25,count);
for(n = 26; n <= 100000; n++){
tot = totient(n); if(tot == n-1)
count++;
if(n == 100 || n == 1000 || n%10000 == 0){ printf("\nNumber of primes up to %6d = %4d\n", n, count); } }
return 0; } </lang>
Output :
n φ prime --------------- 1 1 False 2 1 True 3 2 True 4 2 False 5 4 True 6 2 False 7 6 True 8 4 False 9 6 False 10 4 False 11 10 True 12 4 False 13 12 True 14 6 False 15 8 False 16 8 False 17 16 True 18 6 False 19 18 True 20 8 False 21 12 False 22 10 False 23 22 True 24 8 False 25 20 False Number of primes up to 25 = 9 Number of primes up to 100 = 25 Number of primes up to 1000 = 168 Number of primes up to 10000 = 1229 Number of primes up to 20000 = 2262 Number of primes up to 30000 = 3245 Number of primes up to 40000 = 4203 Number of primes up to 50000 = 5133 Number of primes up to 60000 = 6057 Number of primes up to 70000 = 6935 Number of primes up to 80000 = 7837 Number of primes up to 90000 = 8713 Number of primes up to 100000 = 9592
Go
Results for the larger values of n are very slow to emerge. <lang go>package main
import "fmt"
func gcd(n, k int) int {
if n < k || k < 1 { panic("Need n >= k and k >= 1") }
s := 1 for n&1 == 0 && k&1 == 0 { n >>= 1 k >>= 1 s <<= 1 }
t := n if n&1 != 0 { t = -k } for t != 0 { for t&1 == 0 { t >>= 1 } if t > 0 { n = t } else { k = -t } t = n - k } return n * s
}
func totient(n int) int {
tot := 0 for k := 1; k <= n; k++ { if gcd(n, k) == 1 { tot++ } } return tot
}
func main() {
fmt.Println(" n phi prime") fmt.Println("---------------") count := 0 for n := 1; n <= 25; n++ { tot := totient(n) isPrime := n-1 == tot if isPrime { count++ } fmt.Printf("%2d %2d %t\n", n, tot, isPrime) } fmt.Println("\nNumber of primes up to 25 =", count) for n := 26; n <= 100000; n++ { tot := totient(n) if tot == n-1 { count++ } if n == 100 || n == 1000 || n%10000 == 0 { fmt.Printf("\nNumber of primes up to %-6d = %d\n", n, count) } }
}</lang>
- Output:
n phi prime --------------- 1 1 false 2 1 true 3 2 true 4 2 false 5 4 true 6 2 false 7 6 true 8 4 false 9 6 false 10 4 false 11 10 true 12 4 false 13 12 true 14 6 false 15 8 false 16 8 false 17 16 true 18 6 false 19 18 true 20 8 false 21 12 false 22 10 false 23 22 true 24 8 false 25 20 false Number of primes up to 25 = 9 Number of primes up to 100 = 25 Number of primes up to 1000 = 168 Number of primes up to 10000 = 1229 Number of primes up to 20000 = 2262 Number of primes up to 30000 = 3245 Number of primes up to 40000 = 4203 Number of primes up to 50000 = 5133 Number of primes up to 60000 = 6057 Number of primes up to 70000 = 6935 Number of primes up to 80000 = 7837 Number of primes up to 90000 = 8713 Number of primes up to 100000 = 9592
The following much quicker version (runs in less than 150 ms on my machine) uses Euler's product formula rather than repeated invocation of the gcd function to calculate the totient:
<lang go>package main
import "fmt"
func totient(n int) int {
tot := n for i := 2; i*i <= n; i += 2 { if n%i == 0 { for n%i == 0 { n /= i } tot -= tot / i } if i == 2 { i = 1 } } if n > 1 { tot -= tot / n } return tot
}
func main() {
fmt.Println(" n phi prime") fmt.Println("---------------") count := 0 for n := 1; n <= 25; n++ { tot := totient(n) isPrime := n-1 == tot if isPrime { count++ } fmt.Printf("%2d %2d %t\n", n, tot, isPrime) } fmt.Println("\nNumber of primes up to 25 =", count) for n := 26; n <= 100000; n++ { tot := totient(n) if tot == n-1 { count++ } if n == 100 || n == 1000 || n%10000 == 0 { fmt.Printf("\nNumber of primes up to %-6d = %d\n", n, count) } }
}</lang>
The output is the same as before.
Pascal
Yes, a very slow possibility to check prime <lang pascal>{$IFDEF FPC}
{$MODE DELPHI}
{$IFEND} function gcd_mod(u, v: NativeUint): NativeUint;inline; //prerequisites u > v and u,v > 0
var t: NativeUInt; begin repeat t := u; u := v; v := t mod v; until v = 0; gcd_mod := u; end;
function Totient(n:NativeUint):NativeUint; var
i : NativeUint;
Begin
result := 1; For i := 2 to n do inc(result,ORD(GCD_mod(n,i)=1));
end;
function CheckPrimeTotient(n:NativeUint):Boolean;inline; begin
result := (Totient(n) = (n-1));
end;
procedure OutCountPrimes(n:NativeUInt); var
i,cnt : NativeUint;
begin
cnt := 0; For i := 1 to n do inc(cnt,Ord(CheckPrimeTotient(i))); writeln(n:10,cnt:8);
end;
procedure display(n:NativeUint); var
idx,phi : NativeUint;
Begin
if n = 0 then EXIT; writeln('number n':5,'Totient(n)':11,'isprime':8); For idx := 1 to n do Begin phi := Totient(idx); writeln(idx:4,phi:10,(phi=(idx-1)):12); end
end; var
i : NativeUint;
Begin
display(25);
writeln('Limit primecount'); i := 100; repeat OutCountPrimes(i); i := i*10; until i >100000;
end.</lang>
- Output
number n Totient(n) isprime 1 1 FALSE 2 1 TRUE 3 2 TRUE 4 2 FALSE 5 4 TRUE 6 2 FALSE 7 6 TRUE 8 4 FALSE 9 6 FALSE 10 4 FALSE 11 10 TRUE 12 4 FALSE 13 12 TRUE 14 6 FALSE 15 8 FALSE 16 8 FALSE 17 16 TRUE 18 6 FALSE 19 18 TRUE 20 8 FALSE 21 12 FALSE 22 10 FALSE 23 22 TRUE 24 8 FALSE 25 20 FALSE Limit primecount 100 25 1000 168 10000 1229 100000 9592 real 3m39,745s
alternative
changing Totient-funtion in program atop to Computing Euler's totient function on wikipedia, like GO and C.
Impressive speedup, but trial division is faster for prime checking, cause it stops immediately, if not prime is sure. <lang pascal>function totient(n:NativeUInt):NativeUInt; var
i, quot: NativeINt;
Begin
result := n; //i = 2 checked seperatly //delete true dividers of n kind of 2,4,8,16 ... while not(ODD(n)) do Begin n := n DIV 2; result := result DIV 2; end; i := 3; //i = 3,5,7,9,11.... while i*i <= n do Begin // delete true dividers n kind of i, i², i³ ... repeat quot := n DIV i; //same as if n MOD i = 0 IF n <> quot*i then BREAK else Begin n := quot; dec(result,result DIV i); end; until false; inc(i,2); end; if n> 1 then dec(result,result div n);
end;
function CheckPrimeTrial(n:NativeUint):Boolean; var
i : NativeUint;
begin
result := ODD(n); i := 3; while result AND ( i*i <= n) do Begin result := (n mod i) <> 0; inc(i,2); end;
end;</lang>
- Output
same as above,but by far faster. ... Limit primecount 100 25 1000 168 10000 1229 100000 9592 real 0m0,048s .. 1000000 78498 10000000 664579 real 0m32,428s
Perl 6
This is an incredibly inefficient way of finding prime numbers.
<lang perl6>my \𝜑 = 0, |(1..*).hyper(:8degree).map: -> $t { +(^$t).grep: * gcd $t == 1 };
printf "𝜑(%2d) = %3d %s\n", $_, 𝜑[$_], $_ - 𝜑[$_] - 1 ?? !! 'Prime' for 1 .. 25;
(100, 1000, 10000).map: -> $limit {
say "\nCount of primes <= $limit: " ~ +(^$limit).grep: {$_ == 𝜑[$_] + 1}
}</lang>
- Output:
𝜑( 1) = 1 𝜑( 2) = 1 Prime 𝜑( 3) = 2 Prime 𝜑( 4) = 2 𝜑( 5) = 4 Prime 𝜑( 6) = 2 𝜑( 7) = 6 Prime 𝜑( 8) = 4 𝜑( 9) = 6 𝜑(10) = 4 𝜑(11) = 10 Prime 𝜑(12) = 4 𝜑(13) = 12 Prime 𝜑(14) = 6 𝜑(15) = 8 𝜑(16) = 8 𝜑(17) = 16 Prime 𝜑(18) = 6 𝜑(19) = 18 Prime 𝜑(20) = 8 𝜑(21) = 12 𝜑(22) = 10 𝜑(23) = 22 Prime 𝜑(24) = 8 𝜑(25) = 20 Count of primes <= 100: 25 Count of primes <= 1000: 168 Count of primes <= 10000: 1229
Python
<lang python>from math import gcd
def φ(n):
return sum(1 for k in range(1, n + 1) if gcd(n, k) == 1)
if __name__ == '__main__':
def is_prime(n): return φ(n) == n - 1 for n in range(1, 26): print(f" φ({n}) == {φ(n)}{', is prime' if is_prime(n) else }") count = 0 for n in range(1, 10_000 + 1): count += is_prime(n) if n in {100, 1000, 10_000}: print(f"Primes up to {n}: {count}")</lang>
- Output:
φ(1) == 1 φ(2) == 1, is prime φ(3) == 2, is prime φ(4) == 2 φ(5) == 4, is prime φ(6) == 2 φ(7) == 6, is prime φ(8) == 4 φ(9) == 6 φ(10) == 4 φ(11) == 10, is prime φ(12) == 4 φ(13) == 12, is prime φ(14) == 6 φ(15) == 8 φ(16) == 8 φ(17) == 16, is prime φ(18) == 6 φ(19) == 18, is prime φ(20) == 8 φ(21) == 12 φ(22) == 10 φ(23) == 22, is prime φ(24) == 8 φ(25) == 20 Primes up to 100: 25 Primes up to 1000: 168 Primes up to 10000: 1229
REXX
<lang rexx>/*REXX program calculates the totient numbers for a range of numbers, and count primes. */ parse arg N . /*obtain optional argument from the CL.*/ if N== | N=="," then N= 25 /*Not specified? Then use the default.*/ tell= N>0 /*N positive>? Then display them all. */ N= abs(N) /*use the absolute value of N for loop.*/ w= length(N) /*W: is used to aligning the output. */ primes= 0 /*the number of primes found (so far).*/
/*if N was negative, only count primes.*/ do j=1 for N; tn= phi(j) /*obtain totient number for a number. */ prime= word('(prime)', 1 + (tn \== j-1 ) ) /*determine if J is a prime number. */ if prime\== then primes= primes+1 /*if a prime, then bump the prime count*/ if tell then say 'totient number for ' right(j, w) " ──► " right(tn, w) ' ' prime end
say say right(primes, w) ' primes detected for numbers up to and including ' N exit /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ gcd: parse arg x,y; do until y==0; parse value x//y y with y x; end /*until*/
return x
/*──────────────────────────────────────────────────────────────────────────────────────*/ phi: procedure; parse arg z; #= z==1
do m=1 for z-1; if gcd(m, z)==1 then #= # + 1; end /*m*/ return #</lang>
- output when using the default input of: 25
totient number for 1 ──► 1 totient number for 2 ──► 1 (prime) totient number for 3 ──► 2 (prime) totient number for 4 ──► 2 totient number for 5 ──► 4 (prime) totient number for 6 ──► 2 totient number for 7 ──► 6 (prime) totient number for 8 ──► 4 totient number for 9 ──► 6 totient number for 10 ──► 4 totient number for 11 ──► 10 (prime) totient number for 12 ──► 4 totient number for 13 ──► 12 (prime) totient number for 14 ──► 6 totient number for 15 ──► 8 totient number for 16 ──► 8 totient number for 17 ──► 16 (prime) totient number for 18 ──► 6 totient number for 19 ──► 18 (prime) totient number for 20 ──► 8 totient number for 21 ──► 12 totient number for 22 ──► 10 totient number for 23 ──► 22 (prime) totient number for 24 ──► 8 totient number for 25 ──► 20 9 primes detected for numbers up to and including 25
- output when using the input of: -100
25 primes detected for numbers up to and including 100
- output when using the input of: -1000
168 primes detected for numbers up to and including 1000
- output when using the input of: -10000
1229 primes detected for numbers up to and including 10000
- output when using the input of: -1000000
9592 primes detected for numbers up to and including 100000
Sidef
The Euler totient function is built-in as Number.euler_phi(), but we can easily re-implement it using its multiplicative property: phi(p^k) = (p-1)*p^(k-1). <lang ruby>func 𝜑(n) {
n.factor_exp.prod {|p| (p[0]-1) * p[0]**(p[1]-1) }
}</lang>
<lang ruby>for n in (1..25) {
var totient = 𝜑(n) printf("𝜑(%2s) = %3s%s\n", n, totient, totient==(n-1) ? ' - prime' : )
}</lang>
- Output:
𝜑( 1) = 1 𝜑( 2) = 1 - prime 𝜑( 3) = 2 - prime 𝜑( 4) = 2 𝜑( 5) = 4 - prime 𝜑( 6) = 2 𝜑( 7) = 6 - prime 𝜑( 8) = 4 𝜑( 9) = 6 𝜑(10) = 4 𝜑(11) = 10 - prime 𝜑(12) = 4 𝜑(13) = 12 - prime 𝜑(14) = 6 𝜑(15) = 8 𝜑(16) = 8 𝜑(17) = 16 - prime 𝜑(18) = 6 𝜑(19) = 18 - prime 𝜑(20) = 8 𝜑(21) = 12 𝜑(22) = 10 𝜑(23) = 22 - prime 𝜑(24) = 8 𝜑(25) = 20
<lang ruby>[100, 1_000, 10_000, 100_000].each {|limit|
var pi = (1..limit -> count_by {|n| 𝜑(n) == (n-1) }) say "Number of primes <= #{limit}: #{pi}"
}</lang>
- Output:
Number of primes <= 100: 25 Number of primes <= 1000: 168 Number of primes <= 10000: 1229 Number of primes <= 100000: 9592
zkl
<lang zkl>fcn totient(n){ [1..n].reduce('wrap(p,k){ p + (n.gcd(k)==1) }) } fcn isPrime(n){ totient(n)==(n - 1) }</lang> <lang zkl>foreach n in ([1..25]){
println("\u03c6(%2d) ==%3d %s" .fmt(n,totient(n),isPrime(n) and "is prime" or ""));
}</lang>
- Output:
φ( 1) == 1 φ( 2) == 1 is prime φ( 3) == 2 is prime φ( 4) == 2 φ( 5) == 4 is prime φ( 6) == 2 φ( 7) == 6 is prime φ( 8) == 4 φ( 9) == 6 φ(10) == 4 φ(11) == 10 is prime φ(12) == 4 φ(13) == 12 is prime φ(14) == 6 φ(15) == 8 φ(16) == 8 φ(17) == 16 is prime φ(18) == 6 φ(19) == 18 is prime φ(20) == 8 φ(21) == 12 φ(22) == 10 φ(23) == 22 is prime φ(24) == 8 φ(25) == 20
<lang zkl>count:=0; foreach n in ([1..10_000]){ // yes, this is sloooow
count+=isPrime(n); if(n==100 or n==1000 or n==10_000) println("Primes <= %,6d : %,5d".fmt(n,count));
}</lang>
- Output:
Primes <= 100 : 25 Primes <= 1,000 : 168 Primes <= 10,000 : 1,229