La spirale des nombres premiers de UlamRenée De Graeve et Bernard Parisse2018 |
Contents
- 1 Introduction
- 2 Programme qui écrit les entiers de 1 à en spirale
- 3 Programme écrivant les chiffres de 1 à au fur et à mesure
- 4 Le programme des nombres premiers écrits en spirale avec leurs affixes
- 5 La spirale des nombres premiers avec la fonction faffixe
- 6 La spirale des carrés rouge représentant les nombres premiers
- 7 Programmes qui ne teste que les nombres et
- 8 Les programmes utilisés
1 Introduction
En 1963, lors d’une communication ennuyeuse Stanislas M. Ulam de l’université
de Los Alamos écrit les entiers naturels selon une spirale, et il entoure
les nombres premiers (ici ils seront écrits en rouge). À sa grande surprise
il obtient beaucoup d’alignement.
Voici la spirale de Ulam et le crible d’Eratosthène pour les entiers de 1
à 56 :
2 Programme qui écrit les entiers de 1 à en spirale
On peut choisir :
- soit constituer la spirale au fur et à mesure : c’est le choix de Bernard Parisse.
- soit écrire une fonction qui à un entier de renvoie son affixe dans la spirale : c’est le choix de Renée De Graeve.
3 Programme écrivant les chiffres de 1 à au fur et à mesure
3.1 Déscription de l’algorithme
Les nombres à écrire sont écrits selon 4 directions :
on appelle dir la variable qui indique la direction :
si dir vaut 1, on écrit les nombres de gauche à droite selon l’axe réel,
si dir vaut i, on écrit les nombres de bas en haut selon l’axe imaginaire,
si dir vaut -1, on écrit les nombres de droite à gauche selon l’axe réel,
si dir vaut -i, on écrit les nombres de haut en bas selon l’axe imaginaire.
Au départ on écrit le nombre 1 à l’origine du repère puis,
on écrit le nombre 2 de gauche à droite selon l’axe réel (i.e à droite du 1 ) puis on change de direction et
on écrit le nombre (3) de bas en haut selon l’axe imaginaire (i.e au dessus du 2), puis on change de direction et
on écrit 2 nombres (4 et 5) de droite à gauche selon l’axe réel,
puis on change de direction et
on écrit 2 nombres (6 et 7) de haut en bas gauche à droite selon l’axe
réel, puis on change de direction et
on écrit 3 nombres (8,9,10) de gauche à droite selon l’axe réel
puis on change de direction et
on écrit 3 nombres (11,12,13) de bas en haut selon l’axe imaginaire,
puis on change de direction et
on écrit 4 nombres (14,15,16,17) de droite à gauche selon l’axe réel,
puis on change de direction et
on écrit 4 nombres (18,19,20,21) de haut en bas selon l’axe imaginaire,
puis on change de direction et
on écrit 5 nombres (22,23,24,25,26) de gauche à droite selon l’axe réel
puis on change de direction et
on écrit 5 nombres (27,28,29,30,31) de bas en haut selon l’axe imaginaire,
puis on change de direction etc....
Combien faut-il écrire d’entiers sans changer de direction ?
Soit k le nombre d’entiers à écrire sans changer de direction.
Au début k vaut 0 et dir vaut 1 eton écrit le nombre 1 à
l’origine du repère puis, on augmente k de 1 i.e k
vaut 1, donc on écrit 2 à droite de 1, puis on change de direction i.e.
dir:=dir*i.
Maintenant dir vaut i et on ne change pas k donc on écrit 3 au
dessus de 2, puis on change de direction i.e. dir:=dir*i.
Maintenant dir vaut -1 et on augmente k de 1, i.e k vaut 2
donc on écrit 4,5 de droite à gauche selon l’axe réel, puis
on change de direction i.e. dir:=dir*i.
Maintenant dir vaut -i, on ne change pas k donc on écrit 6,7 de
haut en bas puis on change de direction i.e. dir:=dir*i.
Maintenant dir vaut 1 et on augmente k de 1,....
Donc k augmente donc de 1 lorsque la direction vaut 1 ou -1 i.e. quand la
direction est un nombre réel on augmente k de 1.
3.2 Le programme des nombres premiers écrits en spirale au fur et à mesure
On veux avoir avoir un programme dans lequel les nombres entiers de 1 à
sont écrits selon une spirale, en écrivant les nombres premiers en rouge.
Écrire les nombres n’est valable que losque est petit. On va donc aussi écrire dans lequel on ne dessine que des carr’es rouges à l’emplacement des nombres premiers, les nombres entiers de 1 à étant bien sûr
écrits selon une spirale.
Ici on écrit les 2 programmes en un seul grâce au paramètre nombre :
lorsque nombre vaut 1 on écrit les nombres selon une spirale en écrivant les nombres premiers en rouge et
lorsque nombre vaut 0 on ne dessine que des carr’es rouges à l’emplacement des nombres premiers.
On tape :
fonction spirale2prem(n,nombre=0) local L,j,k,N,z,dir; N:=1; z:=0; L:=[]; dir:=1; k:=0; si nombre alors L.append(couleur(legende(z,N),0)); fsi; tantque N<n faire si im(dir)==0 alors k++; fsi; pour j de 1 jusque k faire z += dir; N += 1; si N==n+1 alors break fsi; si nombre alors si isprime(N) alors L.append(couleur(legende(z,N),1)); sinon L.append(couleur(legende(z,N),0));fsi; sinon si isprime(N) alors L.append(couleur(carre(z,z+1),rouge+rempli)); fsi; fsi; fpour; dir := i*dir; ftantque; afficher(N); return L; ffonction:;
onload
3.3 La spirale des nombres premiers et des premiers jumeaux
On peut modifer ce programme pour avoir les nombres premiers de 1 à répéré par des carrés rouge ou bleu pour les nombres premiers jumeaux. On remplit la spirale au fur et à mesure.
fonction spiralejum(n) local L,j,k,N,z,dir,Np,zp; N:=1; z:=0; L:=[]; dir:=1; //L.append(couleur(carre(z,z+1),rouge+rempli)); k:=0;Np:=2;zp:=1; tantque N<n faire si im(dir)=0 alors k++; fsi; pour j de 1 jusque k faire z += dir; N += 1; si isprime(N) alors si N==Np+2 alors L.append(couleur(carre(zp,zp+1),bleu+rempli)); L.append(couleur(carre(z,z+1),bleu+rempli)); sinon L.append(couleur(carre(z,z+1),rouge+rempli)); fsi; zp:=z;Np:=N; fsi; fpour; dir := i*dir; ftantque; afficher(N); return L; ffonction:;
onload
3.4 La spirale des nombres premiers et des premiers jumeaux débutant à
On remplit, au fur et à mesure, la spirale débutant à par des carrés bleu pour les nombres premiers jumeaux et rouge pour les nombres premiers non jumeaux.
fonction spiralejumn0(n0,n) local L,j,k,N,z,dir,Np,zp; N:=n0; z:=0; L:=[]; dir:=1; //L.append(couleur(carre(z,z+1),rouge+rempli)); k:=0;Np:=2;zp:=1; tantque N<n faire si im(dir)=0 alors k++; fsi; pour j de 1 jusque k faire z += dir; N += 1; si isprime(N) alors si N==Np+2 alors L.append(couleur(carre(zp,zp+1),bleu+rempli)); L.append(couleur(carre(z,z+1),bleu+rempli)); sinon L.append(couleur(carre(z,z+1),rouge+rempli)); fsi; zp:=z;Np:=N; fsi; fpour; dir := i*dir; ftantque; afficher(N); return L; ffonction:;
onload
4 Le programme des nombres premiers écrits en spirale avec leurs affixes
4.1 L’affixe des nombres entiers écrits selon une spirale: faffixe
Soit la fonction qui à un entier renvoie son affixe dans la
spirale, en prenant comme repère orthonormé
().
On a donc :
, , , , ,....,,...
On remarque :
-
lorsque la spirale forme un carré (par exemple
ou ) les carrés se terminant par ont
pour affixe et
les carrés se terminant par ont pour affixe .
Donc :
si est pair alors et
si est impair alors . - si est pair et si , on a :
re()=re()-
im()=im()-.
Donc :
si alors
et - si est pair et si on a :
avec et
re()=re()+
im()=im()=.
Donc :
si on a :
- si est impair et si alors
re()=re()+
im()=im()-.
donc
et donc
- si est impair et si on a :
avec et
re()=re()-
im()=im()=.
donc
On écrit la fonction faffixe :
fonction faffixe(n) local a,k,p,q,j; si n<=0 or type(n)!=integer alors return "bad argument type"; fsi; a:=floor(sqrt(n));k:=n-a^2; si est_impair(a) alors si k==0 alors return (a-1+i*(-a+1))/2; fsi; si k<=a+1 alors return (a+1+i*(-a+1))/2+i*(k-1); fsi; return (a+1+i*(a+1))/2-(k-a-1); sinon si k==0 alors return (-a+2+i*a)/2; fsi; si k<=a+1 alors return (-a+i*a)/2-(k-1)*i; fsi; return (-a-i*a)/2+k-a-1; fsi; ffonction:;
onload
4.2 La spirale des nombres premiers avec la fonction faffixe
En utilisant la fonction faffixe précédente, on écrit les nombres
entiers de 1 à , selon une spirale, en écrivant les nombres premiers en
rouge.
On tape :
fonction spirale(n) local k,L,b; L:=NULL; pour k de 1 jusque n faire b:=faffixe(k); //L:=L,carre(b,b+1); si est_premier(k) alors L:=L,affichage(legende(b,k),1); sinon L:=L,legende(b,k) ;fsi; fpour; return L; ffonction:;
onload
5 La spirale des nombres premiers avec la fonction faffixe
On peut modifier légèrement ce programme pour écrire les nombres entiers
de à en écrivant les nombres premiers en rouge.
fonction spiralen0(n0,n) local k,L,b; L:=NULL; pour k de n0 jusque n faire b:=faffixe(k-n0+1); //L:=L,carre(b,b+1); si est_premier(k) alors L:=L,affichage(legende(b,k),1); sinon L:=L,legende(b,k) ;fsi; fpour; return L; ffonction:;
onload
5.1 Programme n’affichant que les nombres premiers selon un carré rouge
Le programme spiralprem(n) affiche, selon un carré rouge, les nombres premiers inférieur ou égaux à n selon une spirale.
fonction spiralprem(n) local k,L; L:=NULL; pour k de 1 jusque n faire si est_premier(k) alors L:=L,affichage(carre(faffixe(k),faffixe(k)+1),1+rempli); fsi; fpour; return L; ffonction:;
onload
5.2 Exercice : saffixe une amélioration de faffixe
Dans le programme spiralprem précédent on ne calcule faffixe(n) que lorsque n est premier. Donc, puisque un carré parfait n’est pas un nombre premier, on peut commenter plusieurs instructions :
fonction faffixe0(n) local a,k,p,q,j; //si n<=0 or type(n)!=integer alors return "bad argument type"; fsi; a:=floor(sqrt(n)); k:=n-a^2; si est_impair(a) alors //si k==0 alors return (a-1+i*(-a+1))/2; fsi; si k<=a+1 alors return (a+1+i*(-a+1))/2+i*(k-1); fsi; return (a+1+i*(a+1))/2-(k-a-1); sinon //si k==0 alors return (-a+2+i*a)/2; fsi; si k<=a+1 alors return (-a+i*a)/2-(k-1)*i; fsi; return (-a-i*a)/2+k-a-1; fsi; ffonction:;
onload
Mais alors faffixe1(a^
2) n’est pas correct !
Exercice
Changer la première instruction du programme faffixe0(n) pour obtenir
la fonction saffixe(n) qui renvoie les affixes de tous les entiers n
qui sont strictement positifs.
Correction
Pour faire l’algorithme de faffixe on a repéré les carrés (1,4,9,..
i.e. les croix rouges sur l’illustration suivante) et on a
calculé l’affixe de n en fonction de a= floor(sqrt(n)) et cela
nous a obligé à traité l’affixe des carrés à part (cf tracer1).
Mais ce n’est pas le cas si on choisit de calculer l’affixe de n en
fonction de a= ceil(sqrt(n))-1 (cf tracer2).
On tape :
fonction saffixe(n) local a,k,p,q,j; a:=ceil(sqrt(n))-1; k:=n-a^2; si est_impair(a) alors si k<=a+1 alors return (a+1+i*(-a+1))/2+i*(k-1); fsi; return (a+1+i*(a+1))/2-(k-a-1); sinon si k<=a+1 alors return (-a+i*a)/2-(k-1)*i; fsi; return (-a-i*a)/2+k-a-1; fsi; ffonction:;
onload
6 La spirale des carrés rouge représentant les nombres premiers
fonction spiraleprem(n) local k,L,b; L:=NULL; pour k de 1 jusque n faire b:=saffixe(k); si est_premier(k) alors L:=L,affichage(carre(b,b+1),1+rempli); fsi; fpour; return L; ffonction :; fonction spiralepremn0(n0,n) local k,L,b; L:=NULL; pour k de n0 jusque n faire b:=saffixe(k-n0+1); si est_premier(k) alors L:=L,affichage(carre(b,b+1),1+rempli); fsi; fpour; return L; ffonction:;
onload
7 Programmes qui ne teste que les nombres et
En effet les nombres premiers strictement supérieur à 3 sont soit de la forme : ou pour entier strictement positif est divisible par 6, est divisible par 2, est divisible par 3, est divisible par 2. donc seuls et peuvent être premiers
7.1 La spirale des nombres premiers débutant à 1 ou à
Lorsqu’on débute la spirale par , on peut avoir un programme plus simple
si on suppose que est un mulitple de 6.
Comme on progresse de 6 en 6 en peut avoir une spirale qui va au delà de .
fonction spiraleprem6(n) local k,L,a,b,z1,r; L:=NULL; r:=irem(n,6); // pour 2 et 3 L:=L,affichage(carre(1,2),1+rempli); L:=L,affichage(carre(1+i,2+i),1+rempli); pour k de 6 jusque n+6-r pas 6 faire (a,b):=(est_premier(k-1),est_premier(k+1)); si a==1 alors z1:=saffixe(k-1) L:=L,affichage(carre(z1,z1+1),1+rempli); fsi; si b==1 alors z1:=saffixe(k-1); L:=L,affichage(carre(z1,z1+1),1+rempli); fsi; fpour; return L; ffonction:; fonction spiraleprem6n0(n0,n) local k,L,a,b,r,z1,r0,n1; L:=NULL; r0:=irem(n0,6); r:=irem(n,6); //n+(6-r)=6*q+r0+(6-r0)=6*(q+1) pour k de n0 jusque n0+6-r faire b:=saffixe(k-n0+1); si est_premier(k) alors L:=L,affichage(carre(b,b+1),1+rempli); fsi; fpour; n1:=n0+6-r0; pour k de n1 jusque n+6-r pas 6 faire (a,b):=(est_premier(k-1),est_premier(k+1)); si a==1 alors z1:=saffixe(k-n0); L:=L,affichage(carre(z1,z1+1),1+rempli); fsi; si b==1 alors z1:=saffixe(k+2-n0) L:=L,affichage(carre(z1,z1+1),1+rempli); fsi; fpour; return L; ffonction:;
onload
7.2 La spirale des nombres premiers et les nombres premiers jumeaux débutant à 1 ou à
Les nombres premiers jumeaux sont 2 nombres premiers dont la différence vaut 2.
On ne sait toujours pas si il y en a une infinité de nombres premiers
jumeaux.
On rajoute la possibilité de placer la spirale au point d’affixe z0
fonction spiralejumeaux6(z0,n) local k,L,a,b,z1,z2 ; L:=NULL; // pour 2 et 3 L:=L,affichage(z0+carre(1,2),1+rempli); L:=L,affichage(z0+carre(1+i,2+i),4+rempli); pour k de 6 jusque n-1 pas 6 faire (a,b):=(est_premier(k-1),est_premier(k+1)); si a+b!=0 alors z1:=saffixe(k-1);z2:=saffixe(k+1) si [a,b]==[1,1] alors L:=L,affichage(z0+carre(z1,z1+1),4+rempli); L:=L,affichage(z0+carre(z2,z2+1),4+rempli); sinon si a==1 alors L:=L,affichage(z0+carre(z1,z1+1),1+rempli); sinon L:=L,affichage(z0+carre(z2,z2+1),1+rempli); fsi; fsi; fsi; fpour; return L; ffonction:; fonction spiralejumeaux6n0(z0,n0,n,nombre=0) local k,L,a,b,z1,z2,n1,r0,r; L:=NULL; r0:=irem(n0,6);r:=irem(n,6); si n0<=5 alors pour k de n0 jusque 2 faire si est_premier (k) alors z1:=saffixe(k-n0+1); L:=L,affichage(z0+carre(z1,z1+1),1+rempli); si nombre alors L:=L,affichage(legende(z0+z1,k),0);fsi; fsi; fpour; z1:=saffixe(3-n0+1); L:=L,affichage(z0+carre(z1,z1+1),4+rempli); si nombre alors L:=L,affichage(legende(z0+z1,3),0);fsi; sinon pour k de n0 jusque n0+6-r0 faire si isprime(k) alors print(k); z1:=saffixe(k-n0+1); L:=L,affichage(z0+carre(z1,z1+1),1+rempli); si nombre alors L:=L,affichage(legende(z0+z1,k),0);fsi; fsi; fpour; fsi; n1:=n0+6-r0; pour k de n1 jusque n+6-r pas 6 faire (a,b):=(est_premier(k-1),est_premier(k+1)); si a+b!=0 alors z1:=saffixe(k-n0);z2:=saffixe(k+2-n0); si [a,b]==[1,1] alors L:=L,affichage(z0+carre(z1,z1+1),4+rempli); L:=L,affichage(z0+carre(z2,z2+1),4+rempli); si nombre alors L:=L,affichage(legende(z0+z1,k-1),0); L:=L,affichage(legende(z0+z2,k+1),0);4 fsi; sinon si a==1 alors L:=L,affichage(z0+carre(z1,z1+1),1+rempli); si nombre alors L:=L,affichage(legende(z0+z1,k-1),0);fsi sinon L:=L,affichage(z0+carre(z2,z2+1),1+rempli); si nombre alors L:=L,affichage(legende(z0+z2,k+1),0);fsi; fsi; fsi; fsi; fpour; return L; ffonction:;
onload
8 Les programmes utilisés
fonction tabprem(z0,n) local j,k,L,a; L:=NULL;a:=floor(sqrt(n)); pour j de 0 jusque a-1 faire pour k de 1 jusque a faire si isprime(j*a+k) alors L:=L,affichage(carre(z0+k+j*i,z0+k+j*i+1),1+rempli); // L:=L,legende(k+j*i,j*a+k); fsi; fpour; fpour; return L; ffonction:; fonction tabprem6(z0,n) local j,k,L,a; L:=NULL; a:=iquo(n,6); pour j de 0 jusque a-1 faire pour k de 1 jusque 6 faire //L:=L,carre(z0-1+k+j*i,z0+k+1+j*i); si isprime(j*6+k) alors L:=L,affichage(legende(z0-1+k+j*i,j*6+k),1); sinon L:=L,legende(z0-1+k+j*i,j*6+k) ; fsi; fpour; fpour; pour j de 1 jusque n-6*a faire si isprime(6*a+j) alors L:=L,affichage(legende(z0-1+j+a*i,6*a+j),1); sinon L:=L,legende(z0-1+j+a*i,6*a+j) ; fsi; fpour; return L; ffonction :; fonction spir(z0) local L; L:=NULL; L:=L,z0+segment(1+i,i); L:=L,z0+segment(0,i); L:=L,z0+segment(0,2); L:=L,z0+segment(2,2+2*i); L:=L,z0+segment(-1+2*i,2+2*i); L:=L,z0+segment(-1+2*i,-1-i); L:=L,z0+segment(3-i,-1-i); L:=L,z0+segment(3-i,3+3*i); L:=L,z0+segment(-2+3*i,3+3*i); return affichage(L,epaisseur_ligne_5); ffonction :; fonction tracer1(z0) local L; L:=NULL; L:=L,affichage(z0+point(0.5+i*0.5),1+epaisseur_point_5); L:=L,affichage(z0+point(0.5+i*1.5),1+epaisseur_point_5); L:=L,affichage(z0+point(1.5-i*0.5),1+epaisseur_point_5); L:=L,affichage(z0+point(-0.5+i*2.5),1+epaisseur_point_5); L:=L,affichage(z0+segment(0.5+0.5*i,1.5+0.5*i),1); L:=L,affichage(z0+segment(1.5+0.5*i,1.5+1.5*i),1); L:=L,affichage(z0+segment(0.5+1.5*i,-0.5+1.5*i),1); L:=L,affichage(z0+segment(-0.5-0.5*i,-0.5+1.5*i),1); L:=L,affichage(z0+segment(-0.5-0.5*i,0.5-0.5*i),1); L:=L,affichage(z0+segment(2.5-0.5*i,2.5+2.5*i),1); L:=L,affichage(z0+segment(0.5+2.5*i,2.5+2.5*i),1); L:=L,affichage(z0+segment(1.5-0.5*i,2.5-0.5*i),1); return L; ffonction:; fonction tracer2(z0) local L; L:=NULL; L:=L,affichage(z0+point(0.5+i*0.5),1+epaisseur_point_5); L:=L,affichage(z0+point(0.5+i*1.5),1+epaisseur_point_5); L:=L,affichage(z0+point(1.5-i*0.5),1+epaisseur_point_5); L:=L,affichage(z0+point(-0.5+i*2.5),1+epaisseur_point_5); L:=L,affichage(z0+segment(1.5+0.5*i,1.5+1.5*i),1); L:=L,affichage(z0+segment(0.5+1.5*i,1.5+1.5*i),1); L:=L,affichage(z0+segment(-0.5+1.5*i,-0.5-0.5*i),1); L:=L,affichage(z0+segment(-0.5-0.5*i,1.5-0.5*i),1); L:=L,affichage(z0+segment(2.5-0.5*i,2.5+2.5*i),1); L:=L,affichage(z0+segment(-0.5+2.5*i,2.5+2.5*i),1); return L; ffonction:;
onload