Nombres premiers : vérification à plusieurs

Sujets variés concernant le développement en PureBasic
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Nombres premiers : vérification à plusieurs

Message par Ollivier »

Bonjour à vous,

dans un but mathématique assez concrèt, je me suis remis à "miner" des nombres premiers.

À la base, je prépare 100000 nombres premiers en moins d'une demi seconde, puis je simplifie des fractions avec. C'est le même algo pour chercher ces nombres premiers comme pour simplifier une fraction : on divise par une liste successive de facteurs, et on agit en fonction du restant calculé.

Puis, m'est venue la bête et gratuite idée de "miner" plus de nombres premiers que cent-mille, puis de les enregistrer dans un fichier. Le rapport quantité/durée de préparation est alors nettement supérieur : on a pleins de nombres premiers (en l'occurence, plusieurs millions) qui se "succèdent" depuis le 2, et c'est chargé et prêt en moins d'une demi seconde.

J'ai, ensuite, toujours bêtement, eu l'idée de baisser la performance de "minage" et de laisser tourner l'ordinateur. C'est un portable avec une LED qui me prévient, et ce CPU est assez surprenant : il bouffe 2 watts ! Il fait 2000 divisions de test, puis pionce 16 millisecondes, et répète ce cycle pour 2 Wh/H, j'estime qu'on ne va pas me reprocher de gaspiller de l'énergie.

Résultat : je commence à avoir un fichier avec plusieurs dizaines de millions de nombres premiers. En brut 64 bits, c'est 8 octets par nombre premier : ça prend de la place.

J'aimerais compresser le tout, trouver un compromis taux/durée assez correct.

Et c'est là que je tique : si mon algo était faux ! Méthode de recherche, enregistrement : pas sûr que ce soit parfait...

Et puis, bien qu'il y a des "compresseurs" natifs, je suis séduit par des compressions plus simples donc, peut-être plus rapides : ça demande à tester. Et pour tester, il est inutile de tester quelquechose qui a une erreur : un nombre premier qui ne le serait pas, ou bien, un nombre premier qui manque. J'ai quelques statistiques aussi, un peu simplistes, quand Windows ne fait pas n'importe quoi avec les fichiers (c'est un boulet, c'est lourd). Et une de ces statistiques me plaît suffisamment, pour avoir envie de creuser un peu. En l'occurence, c'est l'aspect quand même très stable des écarts entre nombres premiers : des nombres premiers de 8 chiffres ne s'écartent pas de plus de 2^8. Autrement dit, un nombre de 28 bits est l'image d'une somme d'écarts, et ces écarts font, au maximum 8 bits. Ce qui fait une compression de 70% avec simplement une addition pour seul algo de décompression.

Mais, pour ça, il faut être sûr de ne pas avoir fait d'erreurs. Et c'est là que je sollicite des passionnés : j'aimerais qu'on partage différents checksums, d'abord, d'une suite symbolique (les 64 premiers nombres premiers, par exemple), puis des checksums de listes de plus en plus conséquentes.

Alors, je ne fais pas la course. Je me suis fixé un but : collecter tous les nombres premiers < à 2^32. Ça permet déjà des sacrées fractions à 9 chiffres. C'est assez "carré" pour un x64 (ou x86 avec algo non signé), avec un entier x64, on a 2 longs dedans, donc une fraction qui "tient" des milliardièmes infiniment précis entre -2 et +2. Et puis, avec deux quads, on a une belle fraction, qui tient des milliardièmes de milliardièmes infiniment précis en -2 et +2. Et, par la même, avec 4 quads, on a des plages irréprochables avec cette même échelle de précision. Avec tous les nombres premiers inférieurs à 2^32, les fractions décrites "en sus" sont parfaitement simplifiables.

J'aimerais que ces nombres premiers < 2^32 tiennent dans un fichier de quelques mégas, voire 1 seul méga-octet.

Et, me connaisant, je ne fais pas de "demi-couille" : traduction, quand je couille, c'est la grosse merde.

Par application axiomatique, vous dire la valeur du Nième nombre premier ne garantit pas que je n'ai pas fait une double faute de recherche (un excès plus un défaut... Un faux positif accompagné d'un faux négatif).

Quel algorithme de hachage permet cette garantie ? (Et donc de se communiquer diverses clés pas trop longues pour s'assurer d'une collection parfaite)
Avatar de l’utilisateur
SPH
Messages : 4726
Inscription : mer. 09/nov./2005 9:53

Re: Nombres premiers : vérification à plusieurs

Message par SPH »

Perso, je commence sur cette base : :P

Code : Tout sélectionner

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; SPH(2022) - Lister les nombres premiers ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; Tester les nombres de 2 a :
nombre=10000

timer=ElapsedMilliseconds()
Dim nb(nombre) : nb(0)=1 : nb(1)=2

For nb=3 To nombre Step 2
  sq=Sqr(nb)
  For u=3 To sq Step 2
    If nb%u=0
      Goto stop
    EndIf
  Next
  nb(0)+1
  nb(nb(0))=nb
  stop:
Next

Debug "Les nombres premiers de 2 à "+Str(nombre)+" ont été trouvé en "+Str(ElapsedMilliseconds()-timer)+" ms"
For i=1 To nb(0)
  Debug nb(i)
Next

End
http://HexaScrabble.com/
!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.00 - 64 bits
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Nombres premiers : vérification à plusieurs

Message par Ollivier »

Salut SPH,

je suis exactement sur ce même départ.

Code : Tout sélectionner

nb(0) = 1 ; le dernier index de la liste
nb(1) = 2
Je suis en quads.

Code : Tout sélectionner

Debug SizeOf(integer) ; affiche 8
Je vois x86 dans ta signature : SizeOf(integer) t'affiche 4 ?
Avatar de l’utilisateur
SPH
Messages : 4726
Inscription : mer. 09/nov./2005 9:53

Re: Nombres premiers : vérification à plusieurs

Message par SPH »

Ollivier a écrit : dim. 07/août/2022 19:48 Salut SPH,

je suis exactement sur ce même départ.

Code : Tout sélectionner

nb(0) = 1 ; le dernier index de la liste
nb(1) = 2
Je suis en quads.

Code : Tout sélectionner

Debug SizeOf(integer) ; affiche 8
Je vois x86 dans ta signature : SizeOf(integer) t'affiche 4 ?

Code : Tout sélectionner

 Debug SizeOf(integer)
8

===

En fait, je suis sur 2 ordinateurs différents. Alors, comme j'utilise le desktop, je viens de modifier ma signature.
Bon, comme tu as vu dans ma routine, j'ouvre un dim :

Code : Tout sélectionner

Dim nb(nombre)
sans préciser si c'est un quad ou pas. Perso, ça dépend jusqu'où on veux aller.

Quel est ton code ?
J'ai cru comprendre que tu pouvais tester la primalité d'un nombre avec une formule. Laquelle ?
http://HexaScrabble.com/
!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.00 - 64 bits
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Nombres premiers : vérification à plusieurs

Message par Ollivier »

C'est pour aller, cool, vers un nombre premier autour de 4 milliards. (le plus grand nombre premier qu'on peut stocker dans 32 bits non signé, en fait)

Code : Tout sélectionner

Global FileName.s = "primes.dta" ; bien régler le bon chemin de fichier

; le tableau
Structure primes
    
    Array p.i(0)
    
EndStructure

; pour rajouter un nombre
Procedure primesAdd(*this.primes, n)
    With *this
        Define max = ArraySize(\p() )
        Define i = \p(0) + 1
        Repeat
            If i > max
                max + 1
                max << 1
                max - 1
            EndIf
        Until i <= max
        ReDim \p(max)
        If i > \p(0)
            \p(0) = i
        EndIf
        \p(i) = n
    EndWith
EndProcedure

; pour afficher la liste
Procedure primesDebug(*this.primes)
    With *this
        Debug ArraySize(\p() )
        For i = 0 To \p(0)
            Debug Str(i) + " : " + Str(\p(i) )
        Next        
    EndWith
EndProcedure

; retourne un facteur premier détecté dans n
Procedure primesFactor(*this.primes, n)
    Static j
    With *this
        For i = 1 To \p(0)
            If j > 2047
                j = 0
                Delay(16)
            EndIf
            j + 1            
            p = \p(i)
            If n % p = 0
                ProcedureReturn \p(i)
            EndIf
            If p * p > n
                Break
            EndIf
        Next        
    EndWith
    ProcedureReturn 0
EndProcedure

; pour sauvegarder
Procedure primesSave(*this.primes, file.s)
    With *this
        Define size = (ArraySize(\p() ) + 1) * SizeOf(integer)
        Define addr = @\p(0)
        Define fileN = CreateFile(#PB_Any, file)
        WriteData(fileN, addr, size)
        CloseFile(fileN)
    EndWith
EndProcedure

; pour charger la liste
Procedure primesLoad(*this.primes, file.s)
    With *this
        Define size = FileSize(file) / SizeOf(integer) - 1
        If size <= 0
            ReDim \p(1)
            \p(0) = 1
            \p(1) = 2
        Else
            ReDim \p(size)
            size + 1
            size * SizeOf(integer)
            Define addr = @\p(0)
            Define fileN = ReadFile(#PB_Any, file)
            ReadData(fileN, addr, size)
            CloseFile(fileN)
        EndIf
    EndWith
EndProcedure

; pour quitter avec la croix rouge d'une fenêtre
Procedure quit()
    Static win
    If win
        If WindowEvent() = #PB_Event_CloseWindow
            CloseWindow(win)
            ProcedureReturn 1
        EndIf
    Else
        win = OpenWindow(#PB_Any, 0, 0, 400, 300, "...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    EndIf
EndProcedure

; pour quitter avec [Alt+F4] 
Procedure quit2()
    Static win
    If win
        If WindowEvent() = #PB_Event_CloseWindow
            CloseWindow(win)
            ProcedureReturn 1
        EndIf
    Else
        win = OpenWindow(#PB_Any, 0, 0, 1, 1, "...", #PB_Window_Maximize | #PB_Window_BorderLess)
        SetWindowColor(win, 0)
    EndIf
EndProcedure

; pour rechercher et stocker les nombres premiers
Procedure primesSearch(*this.primes, i, *quit)
    With *this
        Repeat
            If primesFactor(*this, i) = 0
                primesAdd(*this, i)
            EndIf
            i + 1
        Until CallFunctionFast(*quit)
    EndWith
EndProcedure

; principe
Define *p.primes = AllocateMemory(SizeOf(primes) )
InitializeStructure(*p, primes)
primesLoad(*p, fileName)
n = *p\p(0)
n = *p\p(n)
n + 1
primesSearch(*p, n, @quit2() )
primesSave(*p, fileName)
MessageRequester(Str(*p\p(0) ), Str(*p\p(*p\p(0) ) ) )
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Nombres premiers : vérification à plusieurs

Message par Ollivier »

Pour résumer

1) bien préciser un fichier avec chemin complet en 1ère ligne
2) couper le débugger et démarrer le programme
3) avec Alt+Tab tu peux faire autre chose (vérifier les ressources CPU)
4) ça enregistre en retournant dessus (l'économiseur noir) et tapant Alt+F4
5) Il enregistre et t'affiche le nombre de nombres premiers trouvés et le dernier nombre premier qui a été trouvé.

Il est juste optimisé avec la méthode de Fibonacci pour éviter de trop diviser.

Etrangement, je le laisse tester tous les nombres même les pairs. Ça évite quelques erreurs de statistique. Et le CPU semble les prédire, donc, tant qu'à faire.

Mais comment avoir confiance à une empreinte ?
PAPIPP
Messages : 534
Inscription : sam. 23/févr./2008 17:58

Re: Nombres premiers : vérification à plusieurs

Message par PAPIPP »

Bonjour Ollivier

Je vois que tu es toujours sur une optimisation des nombres premiers.
J’ai testé ton prg, mais mon écran s’est trouvé dans le noir.
Avec alt F4 j’ai pu l’arrêter

J’ai ensuite réalisé le prg suivant pour vérifier ce qui il avait dans le fichier primes.dta
Les cent premiers nb sont bien premiers.

Je voudrai savoir quel est ton objectif car tous les nombre dans le fichier ne sont pas compressés.
Après lancement du prg peut-on garder la possibilité de continuer à travailler.

Code : Tout sélectionner

Global FileName.s = "g:\primes.dta"
If ReadFile(0, FileName) 
  length = Lof(0)                            ; Lit la taille en octets du fichier 
  *MemoryID = AllocateMemory(length)         ; alloue un bloc mémoire de la taille du fichier
  If *MemoryID
    bytes = ReadData(0, *MemoryID, length)   ; Lit les données du fichier et les place dans le bloc mémoire
    Debug "Nombre d'octets lus: " + Str(bytes)
  EndIf
  CloseFile(0)
EndIf
nbprem=bytes/4
Debug _n(length)+_n(nbprem)
np=0
np0=0
For i =0  To length Step 4
  prem=PeekI(*MemoryID+i)
  If prem>0
    Debug prem
    np+1
  Else
    np0+1
  EndIf
Next
Debug _n(np)+_n(np0)+_n(nbprem)+_n(np+np0)
    
A+
Il est fort peu probable que les mêmes causes ne produisent pas les mêmes effets.(Einstein)
Et en logique positive cela donne.
Il est très fortement probable que les mêmes causes produisent les mêmes effets.
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Nombres premiers : vérification à plusieurs

Message par Ollivier »

Bonjour PAPIPP,

je dois avouer être ravi par ton intervention. Je pensais forcément à toi qui a d'ailleurs raconté avoir collectionné et stocké des nombres premiers dans des fichiers. Il faudra que je retrouve le lien de cette description.

Alors, aucun nombre n'est compressé dans ce programme : ils font << brutalement 8 octets pièce >> !

Avant de reprendre le travail, et, étant un peu malade (un comble pour un été), je testais les différents compresseurs de pureBasic et aucun ne détecte que les gaps, les écarts ne dépassent pas 256, les 8 bits d'un octet.

Je tâcherai de poster le dernier petit code pour demain matin, qui visualise cette évolution moyenne de l'écart, avec, grâce à ArS une illustration, sur 20 millions de valeurs environ. On a une moyenne de 20, bien en-deça de 256.

Cet écart moyen grandit mais ça laisse le temps.

Mon but :
- chercher les nombres premiers de 32 bits (jusqu'à 4 milliards environ)
- les compresser (tenter la barre du seul mégaoctet)
- les utiliser pour un programme de calcul mathématiques (simplification des fractions et des racines) de nombres de 64 bits

Pour le petit programme actuel, il met dans le noir ! Effectivement, c'est le but : l'exécuter, comme un économiseur d'écran (si on n'utilise pas l'ordinateur) ou pas. En tapant Alt+Tab, on bascule vers toute autre tâche. Et on peut remarquer que le "minage", la recherche des nombres premiers prend peu de ressources CPU (moi, j'ai 4% qui s'affiche).

Le but à plusieurs, c'est de vérifier qu'on a les mêmes nombres premiers. Il y a une librairie native dans pureBasic, mais, un peu comme la librairie sur la compression de données qui n'arrive pas à compresser mieux que ce que l'on peut faire soi sans trop de difficulté (si chaque écart entre deux nombres premiers est inférieur à 256, par simple addition/soustraction, on compresse manuellement les nombres premiers dans un seul octet : je ne sais pas, par contre si cette limite est franchie pour les nombres premiers jusqu'à 4 milliards environ, en tout cas, jusqu'à 400 millions environ, pas de souci, si je ne me suis pas trompé de nombres !) j'ai donc peur que les différentes fonctions de signature (CRC32, etc...) ne m'induisent pas en erreur, et n'induisent pas en erreur un groupe de personnes qui vérifieraient entre eux, par ce type de signature, qu'ils ont la bonne liste des nombres premiers.

Quand tu quittes le programme avec Alt+F4, il y a un message qui s'affiche : dans mon cas, j'ai 21995833 (en titre de message), c'est la quantité totale de nombres premiers qu'il a stockés et enregistrés dans le fichier (c'est Alt+F4 qui déclenche l'enregistrement, petite subtilité). Et j'ai, dans ce message, 413075863, c'est le dernier nombre premier qu'il a trouvé.

Or, tout comme les empreintes (CRC32, etc...), vous dire que le 21 995 833 ième nombre premier est 413 075 863, ne me semble pas être une preuve suffisante, que j'ai bien enregistré la bonne liste complète, et sans erreur, des nombres premiers entre 2 et 413 075 863, inclus.

En quelle méthode, pourrait-on avoir confiance ?

Et très heureux de te lire.



PS : si toi, ou quiconque, souhaitez me "dépasser" avec ce programme, il y a une valeur à augmenter dedans qui est ici à 2047 : c'est le nombre de vérifications que le programme exécute avant de rendre la main avec Delay() et donc, d'attendre d'avoir, à nouveau la main quelques 16 millisecondes plus tard.

Par contre, attention à votre mémoire vive, parce que tout reste en mémoire tant que vous ne quittez pas le programme : il n'y a pas d'enregistrement partiel.
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Nombres premiers : vérification à plusieurs

Message par Ollivier »

Je constate avec surprise :
- que 436 273 009 semble être un nombre premier
- que 436 273 291 semble être aussi un nombre premier
- qu'il n'y a pas de nombre premier entre ces deux valeurs

donc :

- la différence entre ces deux nombres étant 282;
- 282 étant supérieur à 256;

ma compression du fichier va fonctionner jusqu'à la position qui précède ce gap.

Il est fort probable donc que le 1er fichier fasse 23 méga 163 kilo et 298 octets. Chaque octet sera non signé entre 0 et 255, et représentera un gap entre 2 et 436 273 009.
PAPIPP
Messages : 534
Inscription : sam. 23/févr./2008 17:58

Re: Nombres premiers : vérification à plusieurs

Message par PAPIPP »

@Ollivier

Voici les deux prg qui permettent de trouver les nb premiers entre deux zones
le premier prg génère les tables des différences avec soit p_fact(x) x peut prendre les valeur 5 7 11 13 17 19 23 pour chacune des tables
Ce prg est indispensable pour utiliser le prg de recherche par zone.

Le deuxième est le prg de recherche les nb premiers entre deux zones
il fonctionne de 1 à 2¨(64)-2
il faut éviter d'utiliser des zones trop importantes
fwell à l'époque avait contrôler ce prg et il avait confirmé les résultats

Code : Tout sélectionner

; exemple des p_fact(x)
; p_fact(x)--modulo-----------------Nb_occurrences des différences--------Taux-----------Gain
; 3__________6__________________________2_________________________________0,3333_________66,66%
; 5__________30_________________________8_________________________________0,2666_________73,33%
; 7__________210________________________48________________________________0,2285_________77,14%
; 11_________2310_______________________480_______________________________0,2078_________79,22%
; 13_________30030______________________5760______________________________0,1918_________80,81%
; 17_________510510 ____________________92160_____________________________0,18052________81,94%
; 19_________9699690____________________1658880___________________________0,17102________82,89%
; 23_________223092870__________________36495360__________________________0,16358________83,64%

;  Macro _q_t_
;  		"
;  EndMacro
;  Macro _n (__n)
;  _q_t_#__n#=_q_t_+Str(__n)+" "
;  EndMacro
;  Macro _Q (__Q)
;  _q_t_#__Q#=_q_t_+Str(__Q)+" "
;  EndMacro
EnableExplicit
Define col$="",dif$=""

OpenConsole("Résultats partiel")
Dim T_MODULO.l(12)
Structure colonne
  ;   nb.q
  prem.a
  ; 	dif_prec.l
  dif_prec.a
  
  ; 	Dif_act.l
EndStructure
Structure DIVIS
  NBPFACT.a
  PREMDIV.l
  NBSEQ.l
  MODULO.q
  ;   Array TDIF.a(40000000)  ;; *** ATTENTION   A utiliser avec DATA.A et read.A  mais très lent avec p_fact(23) P_fact(19) est préférable remplacer 40 par 2
  Array TDIF.a(40000000)  
EndStructure
Define SEQD.DIVIS,mess$,nb$,nbs,rest.l,i,modulo,elem,NBprem,Tdep.q,inb,inbp,prem_p,PREM_NB_PREM_AV,NB_PREM,SOM_DIF,vecteur$,NBSEQ,lvecteur,rapportq.d,RAPPORT.D
Define ADRDSEQ.q,AdresdebF.q,AdresFinF.q,Adresdeb.q,delta

; **************** Réalisation du vecteur modulo npp à partir d'une table des nombres premiers des 100 premiers nombres *********
;***** Choix du premier Nb premier pour lequel le vecteur modulo sera appliqué.
;***** pour éviter la génération d'un vesteur trop important nous limiterons ce choix aux 23 premiers nombres premiers soit :2 3 5 7 11 13 17 19 23 29 31
;***** Recherche du modulo < 2*3*5*7*11=2310 éléments du vecteur
SAISIE0:
mess$+"Filtre de réduction des diviseurs"
If Len(mess$)>120
  MessageRequester("Erreur","Colonne Div max 2 3 5 7 11 13 17 19 23"+#CR$+"Relancez le prg") ;
  End
EndIf
nb$=InputRequester(mess$,"Colonne Div max 2 3 5 7 11 13 17 19 23","5") ;
If Val(nb$)>23
  Goto SAISIE0
EndIf
nbs=Val(nb$)
If nbs<1 Or nbs>31
  Goto SAISIE0
EndIf
rest.l=nbs%30
If rest=2 Or rest=3 Or rest=5 Or rest=7 Or rest=11 Or rest=13 Or rest=17 Or rest=19 Or rest=23
Else
  Goto SAISIE0
EndIf 
; NBPFACT=NBS
; FINSAISIE0:
Restore lab_pnbp
i=0
Modulo=1
Repeat
  Read.l ELEM
  If ELEM<>0
    T_modulo(I)=elem
    Modulo*elem
    i+1
  EndIf
Until ELEM=0 Or ELEM=>nbs
ReDim SEQD\TDIF(Modulo+10)
SEQD\MODULO=MODULO 
SEQD\NBPFACT=nbs
NBprem=i-1
nbs=ELEM
Dim tcol.colonne(SEQD\MODULO+2)
;*** Recherche des colonnes ayant des nb premiers ***
tcol(0)\prem=2
tcol(1)\prem=2
Tdep.q=ElapsedMilliseconds()
For inb=2 To modulo+1
  For inbp=0 To nbprem
    If inb % t_modulo(inbp)=0
      tcol(inb)\prem=2
    EndIf
  Next
Next
prem_p=0
PREM_NB_PREM_AV=0
NB_PREM=0
SOM_DIF=0
vecteur$="DIV_"+Str(nbs)+":"+#CRLF$
;****** Recherche des différence entre NB premiers *****
If CreateFile(0,"DIVA_"+Str(nbs)+".PB")         ; création d'un nouveau fichier texte...
  NBSEQ=0
  For inb=2 To modulo+1
    ;     tcol(inb)\nb=inb
    If tcol(inb)\prem=0 And inb>nbs
      If prem_p=0
        prem_p=inb
        PREM_NB_PREM_AV=inb
        vecteur$+"DATA.A  "+Str(inb)+","
        SEQD\PREMDIV=inb
        NBSEQ+1
      Else
        NB_PREM+1
        If nb_prem % 101=0
          If nb_prem % 201=0
            PrintN(_n(NB_prem)+_n(prem_p)+_n(tcol(inb)\dif_prec)+_n(som_dif)+_n(ElapsedMilliseconds()-Tdep)+_n(lvecteur))
          EndIf
          If nb_prem % 5=0  ; ici tous les =101*x  c'est avec 5 que l'on obtient le meilleur résultat
            vecteur$+Str(inb-prem_p)+#CRLF$
            ; 					  SEQD\TDIF(NBSEQ-1)=inb-prem_p
            SEQD\TDIF(NBSEQ)=inb-prem_p
            
            NBSEQ+1
            lvecteur=Len(vecteur$)
            WriteString(0,vecteur$) ;
            vecteur$="Data.A "
          Else
            vecteur$+Str(inb-prem_p)+#CRLF$+"Data.A "
            ; 					  SEQD\TDIF(NBSEQ-1)=inb-prem_p
            SEQD\TDIF(NBSEQ)=inb-prem_p
            
            NBSEQ+1
          EndIf
          
          tcol(inb)\dif_prec=inb-prem_p
          SOM_DIF+(inb-prem_p)
          ; 					tcol(prem_p)\Dif_act=inb-prem_p
          prem_p=inb
        Else
          tcol(inb)\dif_prec=inb-prem_p
          vecteur$+Str(inb-prem_p)+","
          ; 					SEQD\TDIF(NBSEQ-1)=inb-prem_p
          SEQD\TDIF(NBSEQ)=inb-prem_p
          NBSEQ+1
          SOM_DIF+(inb-prem_p)
          ; 					tcol(prem_p)\Dif_act=inb-prem_p
          prem_p=inb
        EndIf
      EndIf
    EndIf
  Next
  ;  tcol(modulo+2)\dif_prec=nb_prem+modulo-(modulo+1)
  NB_PREM+1
  tcol(modulo+2)\dif_prec=PREM_NB_PREM_AV-1
  SEQD\TDIF(NBSEQ)=PREM_NB_PREM_AV-1
  SEQD\TDIF(0)=PREM_NB_PREM_AV-1
  SEQD\NBSEQ=NBSEQ
  ReDim SEQD\TDIF(NBSEQ+2)
  
  ; 	tcol(1)\Dif_act=PREM_NB_PREM_AV-1
  ; 	tcol(1)\nb=1
  SOM_DIF+(PREM_NB_PREM_AV-1)
  rapportq.d=100.0*(modulo-Nb_prem)/modulo
  vecteur$+Str(PREM_NB_PREM_AV-1)+",0 ;"+#CRLF$+";; Modulo="+Str(modulo)+" Nb Elements dans vecteur="+Str(NB_prem)+"  NBPFACT="+Str(SEQD\NBPFACT)+" Nb sequences="+Str(NBSEQ)+"  GAin="+Str(rapportq)+"%"
  
  WriteString(0,vecteur$) ;
  CloseFile(0)            ; ferme le fichier précédemment ouvert et enregistre les données
  PrintN(_n(ElapsedMilliseconds()-Tdep))
  RAPPORT.D=modulo/NB_PREM
  MessageRequester("C'est tout bon","Somme des nb du vecteur="+_n(SOM_DIF)+#CRLF$+_n(modulo)+#CRLF$+"voir le fichier pour le détail du vecteur"+#CRLF$+"Fichier: "+GetCurrentDirectory()+"DIVA_"+Str(nbs)+".PB"+#CRLF$+"Nomnre d'éléments dans le vecteur="+Str(NB_PREM)+" Rapport="+StrD(RAPPORT))
Else
  MessageRequester("Information","Impossible de créer le fichier! DIVA_"+Str(nbs)+".PB")
EndIf
; Adresdeb.l=@SEQD\NBPFACTStructure DIVIS
;   NBPFACT.a
;   PREMDIV.l
;   NBSEQ.l
;   MODULO.q
;   ;   Array TDIF.a(40000000)  ;; *** ATTENTION   A utiliser avec DATA.A et read.A  mais très lent avec p_fact(23) P_fact(19) est préférable remplacer 40 par 2
;   Array TDIF.a(40000000)  
ADRDSEQ.q=@SEQD
AdresdebF.q=@SEQD\NBPFACT
AdresFinF.q=@SEQD\MODULO+SizeOf(quad)
Adresdeb.q=@SEQD\TDIF(0)
delta=AdresFinF-AdresdebF
If CreateFile(1, "MEMA_"+Str(nbs)+".bin")
  WriteData(1,ADRDSEQ ,delta )
  ;   WriteData(1,Adresdebf , 17)
  WriteData(1,Adresdeb , SEQD\NBSEQ+1)
  CloseFile(1)
Else
  MessageRequester("ATTENTION", "Fichier "+ "MEMA_"+Str(nbs)+".bin non créer")
EndIf
;;; Ecriture des 48 colonnes 
col$=""
dif$=""
For inb=0 To modulo+1
 If tcol(inb)\prem=0  
   col$+Str(inb)+","
   dif$+Str(tcol(inb)\dif_prec)+","
   EndIf
 Next 
 PrintN(col$)
 PrintN(dif$)
 ;;; Fin ecriture
 PrintN("C'est fini")
 Input()
CloseConsole()

DataSection
  lab_pnbp:
  Data.l 2,3,5,7,11,13,17,19,23,29,31,0
EndDataSection

DataSection
  lab_pnbp2:
  Data.L   2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97
  Data.L  101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199
  Data.L  211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293
  Data.L  307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397
  Data.L  401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499
  Data.L  503,509,521,523,541,547,557,563,569,571,577,587,593,599
  Data.L  601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691
  Data.L  701,709,719,727,733,739,743,751,757,761,769,773,787,797
  Data.L  809,811,821,823,827,829,839,853,857,859,863,877,881,883,887
  Data.L  907,911,919,929,937,941,947,953,967,971,977,983,991,997,0
EndDataSection
; ***************** Ci dessous les Nombres premiers pour les 1000 premiers nombres
; 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
; 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199
; 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293
; 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397
; 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499
; 503 509 521 523 541 547 557 563 569 571 577 587 593 599
; 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691
; 701 709 719 727 733 739 743 751 757 761 769 773 787 797
; 809 811 821 823 827 829 839 853 857 859 863 877 881 883 887
; 907 911 919 929 937 941 947 953 967 971 977 983 991 997

Ici le deuxième prg de recherche par zone

Code : Tout sélectionner

; algorithme de recherche des nombres PREMIERS par zones 
; ATTENTION ENTRE 1E2-1E1 =90 entre 1E3-1E2=900 entre 1E4-1E3=9000 entre 1E12-1E11= 900000000000
;; et entre 2^63 et 2^64 différence 2^63 = 9223372036854775808
; Le nombre 1 n'est pas par convention un nombre premier.
; Tous les nombres premiers >5 se terminent par 1 3 7 ou 9 seulement
; exemple des p_fact(x)
; p_fact(x)--modulo-----------------Nb_occurrences des différences--------Taux-----------Gain
; 3__________6__________________________2_________________________________0,3333_________66,66%
; 5__________30_________________________8_________________________________0,2666_________73,33%
; 7__________210________________________48________________________________0,2285_________77,14%
; 11_________2310_______________________480_______________________________0,2078_________79,22%
; 13_________30030______________________5760______________________________0,1918_________80,81%
; 17_________510510 ____________________92160_____________________________0,18052________81,94%
; 19_________9699690____________________1658880___________________________0,17102________82,89%
; 23_________223092870__________________36495360__________________________0,16358________83,64%

Macro _HHQ (_HHQ,_pr="$")
  _PR+RSet(Hex(PeekQ(@_HHQ),#PB_Quad),16,"0")
EndMacro

EnableExplicit
; DisableDebugger
; 2 3 5 7 11 13 17 19 23
Global Dim TABTERMIN.Q(4)
Structure ldec 
  DIFF.l
  IND.l
EndStructure
Structure synchro 
  StructureUnion
    SYNCDEC.ldec
    SYNCALP.q
  EndStructureUnion 
  
EndStructure  
Structure DIVIS
  NBPFACT.a
  PREMDIV.l
  NBSEQ.l
  MODULO.q
  Array TDIF.a(37000000)  ;;
EndStructure
Structure INFOTEMP
  NBASE$
  NBASE.Q
  NBASEHEX$
  NBASEDIFB.q
  NBASEIND.q
  NBASEDIFS.q
  NBASERAC.Q
  NBASEP.Q
  NBASEPHEX$
  NBASEPDIF.Q
  NBASEPIND.q
  NBASEPRAC.q
  
  NPLAGE$
  NPLAGE.Q
  NPLAGEHEX$
  
  NPLAGEMAX$    
  
  NBASEM$
  NBASEM.Q
  NBASEMHEX$
  NBASEMP.Q
  NBASEMPHEX$
  NBASEMIND.q
  NBASEMRAC.Q
  
;   FUTBASE$
;   FUTBASED.D
;   FUTBASE.q
;   FUTBASEHEX$
;   ;     FUTBASEP.Q
;   ;     FUTBASEPHEX$
;   FUTBASEIND.q
;   FUTBASERAC.Q
  
EndStructure 
Structure INFOCALC
  NBASE$
  NBASE.Q
  NBASEHEX$
  NBASEDIFB.q
  NBASEIND.q
  NBASEDIFS.q
  NBASERAC.Q
  NBASEP.Q
  NBASEPHEX$
  NBASEPDIF.Q
  NBASEPIND.q
  NBASEPRAC.q
EndStructure  
Global INFOSAISIE.INFOTEMP

Global result$,rest,SEQD.DIVIS,delta_deb.q,NBDIVISIONE.D
Global nbs.l,NBSEQ.l,SEQD.DIVIS,LIMIT$="7FFFFFFFFFFFFFFF",LIMITQ.Q=$7FFFFFFFFFFFFFFF,RACLIM.d=Sqr(LIMITQ)

Define nb$,nb.q,B2DIVIS.q,B2PAS,mess$,quotient.q,ind.l,B1MIN.Q=1E12,pos,B1MIN_DEP.Q,ZONEP.Q,presultat$,resultat$
Define MAX.Q=B1MIN+1E4,nbg$,nbd$,pose.l,t_ind.l,t_col.l,t_ind_dep.l,MAXMAXDIV.q,RAC2.Q,B1MINRAC2.Q,nbseqp,B2IND_MAXDIV,DIF_MAXDIV
Define ind_dep,DIFF,FLAGFIN,IND_NB,CENTM,B2DIVISM,B2INDDD, B2DIVIS$,B2MAXDIV.q,dep_time.q,cent,nbseq_1.q,P_MAXDIV.q,MAXHEX$
Procedure.Q DIVI64_32Q(DIVIDENTE.Q,DIVISEUR.Q)
    Protected  QUOTIENTS.Q
  Global RESTES_.Q  ;; impossible de le placer en shared
  EnableExplicit
  EnableASM 
  MOV ecx,dword[p.v_DIVISEUR]  ;;;; la division euclidienne X=kQ+R avec R<Q nous oblige à utiliser une astuce
  XOr EDX,EDX                  ;;;; pour éviter avec un diviseur trop petit et un dividente trop grand d'avoir un reste de type qword or EDX est de type dword 
  MOV eax,dword[p.v_DIVIDENTE+4]
  DIV ecx
  MOV dword[p.v_QUOTIENTS+4],eax
  MOV eax,dword[p.v_DIVIDENTE]
  DIV ecx
  MOV dword[p.v_QUOTIENTS],eax
  MOV dword[v_RESTES_],edx
  DisableASM 
  ProcedureReturn QUOTIENTs
  DisableExplicit
  EndProcedure  
 Procedure.Q DIVI64_32R(DIVIDENTE.Q,DIVISEUR.Q)
  Shared QUOTIENTS_.Q
  Protected  RESTES_.Q
  EnableASM 
  MOV ecx,dword[p.v_DIVISEUR]  ;;;; la division euclidienne X=kQ+R avec R<Q nous oblige à utiliser une astuce
  XOr EDX,EDX                  ;;;; pour éviter avec un diviseur trop petit et un dividente trop grand d'avoir un reste de type qword or EDX est de type dword 
  MOV eax,dword[p.v_DIVIDENTE+4]
  DIV ecx
  MOV dword[v_QUOTIENTS_+4],eax
  MOV eax,dword[p.v_DIVIDENTE]
  DIV ecx
  MOV dword[v_QUOTIENTS_],eax
  MOV dword[p.v_RESTES_],edx
  DisableASM 
  	ProcedureReturn RESTES_
EndProcedure  
Procedure PREM_1_3_7_9(NBprem.Q);;;; Répartition des Nb premiers par terminaison 1 3 7 9 ********************
 Protected rest10.A
   EnableExplicit
 Rest10.A=DIVI64_32R(NBPREM,10) 
 Select REST10 
    Case 1
      TABTERMIN(1)+1
    Case 3
      TABTERMIN(2)+1
    Case 7
      TABTERMIN(3)+1
    Case 9
       TABTERMIN(4)+1
   Default 
      MessageRequester("Attention " , _HHQ(NBPREM,"")+" n'est pas premier ")
  EndSelect
  DisableExplicit
EndProcedure  

Procedure.s choixdiv()
  Protected     COUR_DIR$,Filtre$,fichier$,Tfichier,fichierp$,leftfich$,RIGHTfich$,deb00.q,deb0.q,ADRDSEQ.q,AdresdebF.q,AdresFinF.q,Adresdeb.q,delta
  EnableExplicit
  COUR_DIR$ = GetCurrentDirectory()
  Filtre$ = "MEMA (MEMA_*.BIN)|MEMA_*.BIN;|Tous les fichiers (*.*)|*.*"
  fichier$=OpenFileRequester("Choisissez un fichier MEMA ou annulez", COUR_DIR$+"\MEMA_17.BIN", Filtre$, 0)
  fichierp$=UCase(Trim(GetFilePart(fichier$)))
  Tfichier=FileSize(Fichier$)
  leftfich$=Left(fichierp$,5)
  RIGHTfich$=Right(fichierp$,4)
  If Tfichier<1 Or Left(fichierp$,5)<>"MEMA_" Or Right(fichierp$,4) <>".BIN"
    MessageRequester( "ATTENTION", "fichier vide ou le nom n'est pas conforme "+ _n(Tfichier)+"  "+_s(fichierp$))
    End
  EndIf
  ;   FICHIER$=choixdiv()
  deb00.q=ElapsedMilliseconds()
  ;************************************************************************************************************************************
  ADRDSEQ=@SEQD
  AdresdebF=@SEQD\NBPFACT
  AdresFinF=@SEQD\MODULO+SizeOf(quad)
  Adresdeb=@SEQD\TDIF(0)
  delta=AdresFinF-AdresdebF
  
  If OpenFile(2,FICHIER$);,#PB_File_SharedRead|#PB_File_NoBuffering)
    ReadData(2,ADRDSEQ ,delta)
    ReDim SEQD\TDIF(SEQD\NBSEQ+1)
    ReadData(2, Adresdeb,SEQD\NBSEQ+1)
    CloseFile(2)
  EndIf
  deb0.q=ElapsedMilliseconds()
  delta_deb.q=deb0-deb00
  EnableExplicit
EndProcedure
Procedure.q SYNCHRO(NBASYNCHRO.Q)
  Protected restd.q,t_ind.q,t_col,ind,INFO.SYNCHRO,t_ind_dep,MODULO.Q
  EnableExplicit
  MODULO.q=SEQD\MODULO 
  restd.q=0
  EnableASM 
  MOV ecx,dword[p.v_MODULO]  ;;;; la division euclidienne X=kQ+R avec R<Q nous oblige à utiliser une astuce
  XOr EDX,EDX                ;;;; pour éviter avec un diviseur trop petit et un dividente trop grand d'avoir un reste de type qword or EDX est de type dword 
  MOV eax,dword[p.v_NBASYNCHRO+4]
  DIV ecx
  ; 	MOV dword[v_quotientp],eax
  MOV eax,dword[p.v_NBASYNCHRO]
  DIV ecx
  MOV dword[p.v_restd],edx
  DisableASM 
  ; 
  ; ;   restd=NBASYNCHRO%SEQD\MODULO 
  t_ind=0
  t_col=1
  
  For ind=0 To SEQD\MODULO 
    If restd<=t_col
      t_ind_dep=t_ind
      Break
    Else 
      t_col+seqd\TDIF(t_ind)
      t_ind+1
    EndIf
  Next
  INFO\SYNCDEC\DIFF=t_col-restd
  INFO\SYNCDEC\IND=t_ind_dep
  ProcedureReturn info\SYNCALP
  DisableExplicit
EndProcedure  

Procedure.s HEX2DEC(HEXS.S)
  EnableExplicit
  Static Dim t_rest.a(1000)
  Protected DIVIDENDE$,vald.q,longt,resultat$,DIVIDP$,DIVIDPR$,QUOTP.q,RESTP.q,quotp$,j,ii,DIVIDP.Q,Irest
  DIVIDENDE$=LTrim(UCase(HEXS))
  vald.q=Val("$"+DIVIDENDE$)
  longt=Len(DIVIDENDE$)
  If vald>0 And longt<17
    resultat$=Str(vald)
  Else  
    Irest=0
    DIVIDP$=""
    DIVIDPR$=""
    quotp$=""
    Repeat 
      For ii=1 To longt
        DIVIDP$=DIVIDPR$+Mid(DIVIDENDE$,ii,1)
        DIVIDP.Q=Val("$"+DIVIDP$)
        ;   QUOTP.q=DIVIDP/10
        ;   RESTP.q=DIVIDP%10
        EnableASM
        MOV ax,word [p.v_DIVIDP]  
        MOV cl,10
        ;   idiv Cl 
        DIV cl  ; utilise moins de cycles machine que idiv
        MOV  [p.v_QUOTP],al
        MOV [p.v_RESTP],AH
        DisableASM
        
        DIVIDPR$=Hex(RESTP)
        quotp$+Hex(QUOTP)
      Next 
      t_rest(Irest)=RESTP
      Irest+1 
      DIVIDENDE$=QUOTP$
      longt=Len(DIVIDENDE$) 
      DIVIDP$=""
      DIVIDPR$=""
      quotp$=""
      
    Until Val("$"+ dividende$)=0
    For j=Irest-1 To 0 Step-1
      resultat$+Str( t_rest(j))
      t_rest(j)=0
    Next
  EndIf
  ProcedureReturn  resultat$
  DisableExplicit
EndProcedure

Procedure.s DEC2HEX(DECI.S)
  EnableExplicit
  Static Dim t_rest.a(1000)
  Protected DIVIDENDE$,vald.q,longt,resultat$,DIVIDP$,DIVIDPR$,QUOTP.q,RESTP.q,quotp$,i,j,ii,DIVIDP.Q,Irest
  DIVIDENDE$=UCase(DECI)
  longt=Len(DIVIDENDE$)
  If Val(DIVIDENDE$)=>0  And longt<20
    vald.q=Val(DIVIDENDE$)
    resultat$=Hex(vald)
  Else  
    irest=0
    DIVIDP$=""
    DIVIDPR$=""
    quotp$=""
    Repeat 
      For ii=1 To longt
        DIVIDP$=DIVIDPR$+Mid(DIVIDENDE$,ii,1)
        DIVIDP.Q=Val(DIVIDP$)
        ;   QUOTP.q=DIVIDP/16
        ;   RESTP.q=DIVIDP%16
        EnableASM
        MOV ax,word [p.v_DIVIDP]  
        MOV cl,16
        ;   div Cl 
        DIV Cl  ; utilise moins de cycles machine que idiv
        MOV  [p.v_QUOTP],al
        MOV [p.v_RESTP],AH
        DisableASM
        
        DIVIDPR$=Str(RESTP)
        quotp$+Str(QUOTP)
      Next 
      t_rest(Irest)=RESTP
      Irest+1 
      DIVIDENDE$=QUOTP$
      longt=Len(DIVIDENDE$) 
      DIVIDP$=""
      DIVIDPR$=""
      quotp$=""
      
    Until Val(dividende$)=0
    For j=Irest-1 To 0 Step-1
      resultat$+Hex( t_rest(j))
      t_rest(j)=0
    Next
  EndIf
  ProcedureReturn  resultat$
  DisableExplicit
EndProcedure
Procedure CALCUL(_NB.S,*SCALCUL.INFOCALC )
  EnableExplicit
  ; PROCEDURE CALCUL(_NB.S,SCALCUL.INFOCALC )
  Static ADR1.q,ADR2.q,ADR3.Q,ADR4.q,FLAG=0 
  Protected POSE,BASEMIN.q,nbasehex$,lnbh,A1.q,A2.q,NBASE.Q,DIFFB.q,difd.d,limitd.d,K.d,RACK.d,DIVMAX.q,NBASEP.q,SYNCDIVIS.SYNCHRO
  Protected MAX_DIV.SYNCHRO,DIVMAXD.d,DIVMAXPD.d,DIVMAXP.q
  If Mid(_NB,1,1)="$"
    nbasehex$=Right(_NB,Len(_NB)-1)
  Else
    POSE=FindString(_NB,"E")
    If pose>0
      BASEMIN.q=ValD(_NB)
      nbasehex$=_HHQ(basemin,"")
    Else 
      nbasehex$=dec2hex(_NB)   
    EndIf 
  EndIf 
  ;   lnbh=len(nbasehex$)
  ;   nbasehex$=ReplaceString(space(16-lnbh)," ","0")+nbasehex$
  nbasehex$=Right("0000000000000000"+nbasehex$,16)
  If lnbh>16 Or nbasehex$>"FFFFFFFFFFFFFFFE" 
    INFOSAISIE\nbase$=""
    INFOSAISIE\NPLAGE$=""
    ProcedureReturn 2 
    Goto FIN
  EndIf
  ;;;;; recherche d'une racine carré de nb à partir de la différence 
  A1.q=Val("$"+Mid(nbasehex$,9,16))
  A2.q=Val("$"+Mid(nbasehex$,1,8))
;   debug _n(A1)+_n(A2)
  
  NBASE.q=0 
  DIFFB.Q=0
  EnableASM  ;; ici recherche en cours pour évaluer le plus précisément la racine carré des nombres >2^63-1
  MOV eax,dword[p.v_A1]
  MOV dword[p.v_NBASE],eax 
  MOV edx,dword[p.v_A2]
  MOV dword [p.v_NBASE+4],edx
  SUB eax,dword[v_LIMITQ] 
  SBB edx,dword[v_LIMITQ+4]
  MOV dword[p.v_DIFFB],eax 
  MOV dword [p.v_DIFFB+4],edx
  If nbasehex$>LIMIT$
    ;;;;; recherche d'une racine carré de nb à partir de la différence 
    difd.d=DIFFB 
    limitd.d=limitq
    K.d=DIFd/LIMITd ;;;; k est défini sur la plage -1 +1 pour une plage div de +$7FFFFFFFFFFFFFFF à -$7FFFFFFFFFFFFFFF
    RACK.D=Sqr(1+K) ;;;; plage de 0 sqr(2)
    DIVMAXD.d=RACLIM *RACK
    DIVMAX.q=divmaxd  ;;limite de recherche des facteurs premiers  de la base
  Else 
    DIVMAX=Sqr(Val("$"+nbasehex$))
  EndIf  
  ;   IF NBASE < SEQD\PREMDIV
  SYNCDIVIS\SYNCALP=SYNCHRO(NBASE)
  *SCALCUL\NBASEP=NBASE+SYNCDIVIS\SYNCDEC\DIFF 
  *SCALCUL\NBASEDIFS=SYNCDIVIS\SYNCDEC\DIFF
  *SCALCUL\NBASEIND=SYNCDIVIS\SYNCDEC\IND
  *SCALCUL\NBASEPHEX$=_HHQ(*SCALCUL\NBASEP,"")
  *SCALCUL\NBASE=NBASE
  *SCALCUL\NBASE$=_NB
  *SCALCUL\NBASEHEX$=nbasehex$
  *SCALCUL\NBASERAC=DIVMAX
  *SCALCUL\NBASEDIFB=DIFFB
  ; *SCALCUL\NBASEIND=INDBASE
  ; *SCALCUL\NBASEP=NBASEP
  If NBASE>0 And NBASE<SEQD\PREMDIV
    *SCALCUL\NBASEP=SEQD\PREMDIV
  EndIf  
  *SCALCUL\NBASEPHEX$=_HHQ(*SCALCUL\NBASEP,"")
  SYNCDIVIS\SYNCALP=SYNCHRO(*SCALCUL\NBASEP)
  *SCALCUL\NBASEPDIF=SYNCDIVIS\SYNCDEC\DIFF 
  *SCALCUL\NBASEPIND=SYNCDIVIS\SYNCDEC\IND
  difd.d=SYNCDIVIS\SYNCDEC\DIFF
  K.d=DIFd/*SCALCUL\NBASEP ;;;; 
  RACK.D=Sqr(1+K)          ;;;; plage de 0 sqr(2)
  DIVMAXPD.d=*SCALCUL\NBASERAC *RACK
  DIVMAXP.q=divmaxpd  ;;
  If divmaxp<4294967296
    divmaxp+1
  EndIf 
   *SCALCUL\NBASEPRAC=DIVMAXP
  FIN:
  DisableExplicit
EndProcedure  
Procedure EXTRINFO(NBE$)  
  Protected pose, basmin.q,nbasehex$,lnbh,A1.q,A2.q,NBASE.Q,DIFFE.Q,difd.d,limitd.d,K.d,RACK.d,DIVMAXD.d,DIVMAX.q,NB$,DIFFB.Q
  Static FLAG=0 
  Shared INF_CAL.INFOCALC, INF_CAL3.INFOCALC
  Protected NBl3$,NB_A_TESTER.Q,NB_DE_DIVISEUR_MPAR.Q,NB_DE_DIVISEUR_MAX.d,KEFFICACE.D,LOG2X.d
  EnableExplicit
  Global T1.Q=ElapsedMilliseconds()
  Select FLAG 
    Case 0
      ;   if INFOSAISIE\nbase$=""
      calcul (NBE$,INF_CAL)
      CopyMemory(INF_CAL,INFOSAISIE,SizeOf(INFOCALC))
    Case 1 
      ;       PRiNTN("X PASSAGE  "+_n(FLAG)+_s(NBE$))
      calcul (NBE$, INF_CAL3)
      ;   calcul (NB$)
      INFOSAISIE\NPLAGE$=NBe$
      INFOSAISIE\NPLAGE=INF_CAL3\NBASE
      INFOSAISIE\NPLAGEHEX$=INF_CAL3\NBASEHEX$
      If INFOSAISIE\NPLAGEHEX$>INFOSAISIE\NPLAGEMAX$
        ProcedureReturn 3
        ;         goto FIN 
      EndIf  
      ;**********************************  Recherche infos de NBASE MAX  *********************************** 
      INFOSAISIE\NBASEM=INFOSAISIE\NBASE+INFOSAISIE\NPLAGE
      INFOSAISIE\NBASEMHEX$=_HHQ(INFOSAISIE\NBASEM,"")
      NBl3$="$"+INFOSAISIE\NBASEMHEX$
      INFOSAISIE\NBASEM$=NBl3$
      
      If INFOSAISIE\NBASEMHEX$>LIMIT$
        A1.q=Val("$"+Mid(INFOSAISIE\NBASEMHEX$,9,16))
        A2.q=Val("$"+Mid(INFOSAISIE\NBASEMHEX$,1,8))
        NBASE.q=0 
        DIFFB.Q=0
        EnableASM  ;; ici recherche en cours pour évaluer le plus précisément la racine carré des nombres >2^63-1
        MOV eax,dword[p.v_A1]
        MOV dword[p.v_NBASE],eax 
        MOV edx,dword[p.v_A2]
        MOV dword [p.v_NBASE+4],edx
        SUB eax,dword[v_LIMITQ] 
        SBB edx,dword[v_LIMITQ+4]
        MOV dword[p.v_DIFFB],eax 
        MOV dword [p.v_DIFFB+4],edx
        ;;;;; recherche d'une racine carré de nb à partir de la différence 
        difd.d=DIFFB 
        limitd.d=limitq
        K.d=DIFd/LIMITd ;;;; k est défini sur la plage -1 +1 pour une plage div de +$7FFFFFFFFFFFFFFF à -$7FFFFFFFFFFFFFFF
        RACK.D=Sqr(1+K) ;;;; plage de 0 sqr(2)
        DIVMAXD.d=RACLIM *RACK
        DIVMAX.q=divmaxd  ;;limite de recherche des facteurs premiers  de la base
      Else 
        DIVMAX=Sqr(Val("$"+INFOSAISIE\NBASEMHEX$))
      EndIf  
;       INFOSAISIE\NBASEMRAC=DIVMAX+1
      INFOSAISIE\NBASEMRAC=DIVMAX
      
      NB_A_TESTER.Q=INFOSAISIE\NPLAGE
      NB_DE_DIVISEUR_MPAR.Q=INFOSAISIE\NBASEMRAC/2+INFOSAISIE\NBASEPRAC/2
      NB_DE_DIVISEUR_MAX.d=1.00*NB_DE_DIVISEUR_MPAR*NB_A_TESTER
      KEFFICACE.D=SEQD\NBSEQ/SEQD\MODULO
      LOG2X.d=Log(NB_DE_DIVISEUR_MAX)*Log10(#E)/Log10(2)
;       NBDIVISIONE.D=KEFFICACE*NB_DE_DIVISEUR_MAX/LOG10(NB_DE_DIVISEUR_MPAR)
      NBDIVISIONE.D=KEFFICACE*NB_DE_DIVISEUR_MAX
;       LOG2X.d=log(NB_DE_DIVISEUR_MAX)*log10(#e)/log10(2)

;       NBMILIS.D=NBDIVISIONE
;       PRINTN("Nombre de divisions max à effectuer :"+strd(NBDIVISIONE,2));;+" Evaluation du temps en ms : "+strd(NBMILIS))
      PrintN("Nombre de divisions max à effectuer :"+StrD(NBDIVISIONE,2))

      ;;;*********** RECXHERCHE DE LA FUTURE  RACINE  et RACINE*RACINE*************************************
      ;   delta=SEQD\TDIF(INFOSAISIE\NBASEPIND)
      ;   INFOSAISIE\FUTBASERAC=INFOSAISIE\NBASEPRAC+delta
      ;   INFOSAISIE\FUTBASE=INFOSAISIE\FUTBASERAC*INFOSAISIE\FUTBASERAC
    Case 2
;       PRiNTN("X PASSAGE  "+_n(FLAG))
    Case 3 
;       PRiNTN("X PASSAGE  "+_n(FLAG))
    Case 4
;       PRiNTN("X PASSAGE  "+_n(FLAG))
  EndSelect
;   PRiNTN("X PASSAGE  "+_n(FLAG)+_s(NBE$))
  FLAG+1 
  
  ;   ProcedureReturn 0
  ; FIN:
  ; logB1MIN=Log10(B1MIN)
  ; logmax=Log10(max-B1MIN)
  ; If logB1MIN+logmax>22
  ;   rmes=MessageRequester(" ATTENTION Temps très long","Oui=>continuez Non=>donnez autre zone",#PB_MessageRequester_YesNo)
  ;   If Rmes = 6        ; le bouton Oui a été choisi (Resultat = 6)
  ;   Else               ; le bouton Non a été choisi (Resultat = 7)
  ;     Goto SAISIE2
  ;   EndIf
  ; EndIf
  DisableExplicit
EndProcedure

Procedure SAISIEBASEPLAGE()
  Protected mess$,nb$,pos,NBASE$,NPLAGE$,reto.l,NBASE.q,DIFFF.Q,NPLAGEMAX$,logB1MIN.D, logmax.D, rmes,hhqhex$,NBASE2.Q
  EnableExplicit
  mess$=""
  SAISIE2:
  mess$+"Base Zone ex: 98765 1E3, $FF875 1E9 ,1E9 1E4"
  
  If Len(mess$)>120
    MessageRequester("Erreur Relancez le Prg","Base  +Zone à explorer Ex: 98765 +1E3, $FF875 1E9, 1E9 +1E4 "+#CR$+"Relancez le prg") ;
    End
  EndIf ;;;                                                                                         7FFFFFFFFFFFFFFF
  nb$=UCase(LTrim(InputRequester(mess$,"Base Zone Ex:98765 1E3, $FF875 1E9, 1E9 1E4","$7FFFFFFFFFFFFF00 +1E3")));
  pos=FindString(nb$," ")
  NBASE$=Trim(Left(nb$,pos))
  NPLAGE$=Trim(Right(NB$,Len(nb$)-pos))
  
  reto.l=EXTRINFO(NBASE$)
  If retO>0
    Goto saisie2
  EndIf 
  ;;;;;;************* Recherche de la plage max possible à utiliser *****************
  NBASE.q=INFOSAISIE\NBASE
  DIFFF.Q=0
  MOV eax,$FFFFFFFE
  MOV edx,$FFFFFFFF
  SUB eax,dword[p.v_NBASE] 
  SBB edx,dword[p.v_NBASE+4]
  MOV dword[p.v_DIFFF],eax 
  MOV dword [p.v_DIFFF+4],edx
  NPLAGEMAX$=_HHQ(DIFFF,"" )
  
  ;   NPLAGEMAX$=_HHQ(DIFFF,"")
  ;   lnbh=len(NPLAGEMAX$)
  ;   NPLAGEMAX$=ReplaceString(space(16-lnbh)," ","0")+NPLAGEMAX$
  INFOSAISIE\NPLAGEMAX$=NPLAGEMAX$
  ;;;*******************************  recherche de la plage à explorer   **************************
  If EXTRINFO(NPLAGE$)
    Goto saisie2
  EndIf 
  INFOSAISIE\NPLAGEMAX$=NPLAGEMAX$
    ;   ProcedureReturn 0
    ; FIN:
  NBASE2.Q=DIVI64_32Q(NBDIVISIONE,10)
  logB1MIN=Log10(NBASE2)+1
  logmax=Log10(INFOSAISIE\NPLAGE)
  If logB1MIN+logmax>15
    rmes=MessageRequester(" ATTENTION Temps très long","Oui=>continuez Non=>donnez autre zone",#PB_MessageRequester_YesNo)
    If Rmes = 6        ; le bouton Oui a été choisi (Resultat = 6)
    Else               ; le bouton Non a été choisi (Resultat = 7)
      Goto SAISIE2
    EndIf
  EndIf

  
  DisableExplicit
EndProcedure
EnableExplicit
Define NB_TOT_DIVIS.q,pos1,k,B1MIN$,B1MINPHEX$,B1MINHEX$,MAX_DIV.SYNCHRO,PAS_IND_NB
OpenConsole()
T1.q=ElapsedMilliseconds()
choixdiv()
SAISIEBASEPLAGE()
PrintN("Fin de la mise en place  temps="+Str(ElapsedMilliseconds()-T1))
MAX=INFOSAISIE\NBASEM
MAXHEX$=_HHQ(MAX,"")
B1MIN=INFOSAISIE\NBASEP
B1MIN_DEP=B1MIN
resultat$=""
NB_TOT_DIVIS=0
presultat$="02 03 05 07 11 13 17 19 23 29 31"
If INFOSAISIE\NBASE=>0 And INFOSAISIE\NBASE < SEQD\NBPFACT 
  pos1=FindString(presultat$,Right("0"+Str(INFOSAISIE\NBASE),2))
;   pos1=FindString(presultat$,Str(INFOSAISIE\NBASE))
  pose=FindString(presultat$,Right("0"+Str(SEQD\NBPFACT),2))+2
  resultat$=Trim(Mid(presultat$,pos1,POSE-pos1))
  NB_TOT_DIVIS=CountString(resultat$," ")+1
;   CreateRegularExpression(0,"[0-9]+"
  If CreateRegularExpression(0,"[0-9]+")
    Dim TResult$(0)
    Nb = ExtractRegularExpression(0,resultat$, TResult$())
    For k = 0 To Nb-1
      Select Right(Tresult$(k),1)
        Case "1"
          TABTERMIN(1)+1
        Case "2"   
          TABTERMIN(0)+1
        Case "3"   
          TABTERMIN(2)+1
        Case "5"   
          TABTERMIN(0)+1
        Case "7"   
          TABTERMIN(3)+1
        Case "9"
          TABTERMIN(4)+1
      EndSelect
    Next
  Else
    Debug RegularExpressionError()
  EndIf
  
;   NB_TOT_DIVIS=(POSE-POS1)/2
  ;   B1MIN=SEQD\NBPFACT
EndIf   

; ******** sysnchronistion des Nombres à tester avec le vecteur des différences ***********
IND_NB=INFOSAISIE\NBASEPIND
B2DIVIS.q=SEQD\PREMDIV
flagfin=0
; B2MAXDIV.q=Pow(B1MIN,0.5)
B2MAXDIV.q=INFOSAISIE\NBASEPRAC  ;;;;;******************************************************
                                 ; MAXMAXDIV.q=Sqr(MAX)   ;;;;;****************************************************** 
MAXMAXDIV.q=INFOSAISIE\NBASEMRAC ;;;;;****************************************************** 
; if B2MAXDIV>MAXMAXDIV
;   B2MAXDIV=MAXMAXDIV
; endif  
PrintN(_n(MAXMAXDIV) +_n(B2MAXDIV))
PrintN(resultat$)

If B1MIN<0
  centm=B1MIN/-100
Else 
  centm=B1MIN/100
EndIf  
;;;;; ***************************** Gestion des diviseurs max *********************
MAX_DIV\SYNCALP =SYNCHRO(B2MAXDIV)
B2IND_MAXDIV=MAX_DIV\SYNCDEC\IND
DIF_MAXDIV=MAX_DIV\SYNCDEC\DIFF
P_MAXDIV=B2MAXDIV+DIF_MAXDIV
; B2MAXDIV=P_MAXDIV
; if MAXMAXDIV-B2MAXDIV<>0
;   *B2MAXDIV=SYNCHRO(B2MAXDIV)
;   B2IND_MAXDIV=*MAXDIV\IND_SYNCHRO
;   DIF_MAXDIV=*MAXDIV\DIFF_SYNCRO
; B2MAXDIV+DIF_MAXDIV

;******************************************************************************************************************
;;****** le prochain B2MAXDIV (A+dif)^2=A^2+2*dif*A+dif^2=  si A=SQR(X)=RAC donc (RAC^2)=X alors => (RAC+dif)^2= (RAC^2)+dif^2+2*dif*RAC=X+dif+(2*RAC*dif)
;;;********************* X+dif(1+2*RAC)
; RAC2=DIF_MAXDIV *(2*B2MAXDIV+DIF_MAXDIV)
; B1MINRAC2=B1MIN+RAC2





; =Str(B1MIN)+" "
B2DIVISm=0
nbseq_1.q=SEQD\NBSEQ-1
nbseq=SEQD\NBSEQ
nbseqp=nbseq+1
dep_time.q=ElapsedMilliseconds()
; B2PAS=SEQD\TDIF(1)
;;;***************************************************************************************************************************
;;;***************************  Début des 2 boucles pour rechercher  les NB premiers dans une zone MIN MAX   *****************
;;;***************************************************************************************************************************
;;;***************************************************************************************************************************
;;;**  Début de la première boucle avec incrémentation des Nombrss le la zone donnée  pour savoir s'ils sont premiers  *******
;;;**  fin de la boucle jusqu'à Until où l'on teste si le nb après incrémention est toujour dans la zone donnée        *******
;;;***************************************************************************************************************************
Repeat 
  B2INDDD=1
  B2PAS=SEQD\TDIF(B2INDDD)
  ;   PRINTN(_NL+_N(B2DIVIS))
  ;;;***************************************************************************************************************************
  ;;;*****  Début de la deuxième boucle avec incrémentation des diviseurs du premier Nb X au dessus de p_fact(X)         *******
  ;;;***                                  jusqu'à la racine du Nb à tester                                               *******
  ;;;***************************************************************************************************************************
  ;;; Info propre à boucle div=B2
  While B2DIVIS<=B2MAXDIV; or FLAGFIN>0
    
    ;   printn(_n(B2DIVIS)+_n(B2PAS)+_n(idivis))
    ;     ;Le nom de @@: signifie étiquette anonyme,vous pouvez avoir défini un grand nombre d'entre eux dans la source.
    ;     ;Symbole @b(ou l'équivalent @r)le plus proche des références du label précédent anonyme
    ;     ;,symbole @f références plus proche de l'étiquette suivante anonyme.
    ;     ;Ces symboles spéciaux sont insensibles à la casse.
    ;;*******************************  TESTS EN ASM ********************************************************************
    ;*************************************** Division d'un nombre de 64 bits par un nombre de 32 bits ******************************************
    EnableASM
    MOV ecx,dword[v_B2DIVIS]
    XOr EDX,EDX
    MOV eax,dword[v_B1MIN+4]
    DIV ecx
    ;   MOV dword[v_quotientp],eax   ;;;; Le reste de la division nous suffit 
    MOV eax,dword[v_B1MIN]
    DIV ecx
    CMP edx,0
    JNZ @f
    INC dword [v_FLAGFIN] 
    Break
    !@@:
    MOV edx,dword[v_B2PAS]
    ADD dword[v_B2DIVIS],edx  ; pas de PB l'addition est réalisée en valeur absolue 
    ADC dword[v_B2DIVIS+4],0  ; pas de PB l'addition est réalisée en valeur absolue 
                              ;     donc $FFFFFFFF =>4294967295 donc pas de risque de dépassement sqr(pow(2,63)-1))=>3037000499,9760496922867524030306 <4294967295
                              ;********************************************************************************************************************************************************
    
    DisableASM
    ;********************************************************************************************************************************************************
    ;********************************************************************************************************************************************************
    ; ;***********************************  Pour accélerer encore l' algo  *******************************
    B2INDDD+1
    If B2INDDD=nbseqp  ;;; inutil de passer en ASM  voir ci dessus c'est plus long de près du double en temps sur la zone  9223372036854774807 1000
      B2INDDD=1        ;;;;;9223372036854770999
    EndIf
    B2PAS=SEQD\TDIF(B2INDDD)
    EnableASM
    ;************************************  Pour accélerer encore l' algo vous pouvez décommentez les 5 lignes PB précedentes ******************************
  Wend
  ;;;;*******************************************************************************************************************************************************
  ;;;; ***********************************************  FIN DE LA DEUXIEME  BOUCLE DES DIVISEURS *************************************************************
  ;;;; ***********************************************  FIN DE LA DEUXIEME  BOUCLE DES DIVISEUR *************************************************************
  ;;;;******************************************************************************************S*************************************************************
  If flagfin=0 And B1MIN<>1
    If B1MIN<0
      cent=B1MIN/-100
    Else 
      cent=B1MIN/100
    EndIf  
    If centm<>cent 
      PrintN(result$)
      centm=cent 
      If B1MIN<0 
        B1MIN$=HEX2DEC(_HHQ(B1MIN,""))
      Else 
        B1MIN$=Str(B1MIN)
      EndIf  
      result$=B1MIN$+" " 
    Else 
      If B1MIN<0 
        B1MIN$=HEX2DEC(_HHQ(B1MIN,""))
      Else 
        B1MIN$=Str(B1MIN)
      EndIf  
      result$+B1MIN$+" " 
    EndIf
    NB_TOT_DIVIS+1
    PREM_1_3_7_9(B1MIN) ;;;; R&partition des Nb premiers par terminaison 1 3 7 9 ******************
  EndIf 
  ;       printn(_NL+_Q(B1MIN)+_s(result$)+_n(FLAGFIN))
  flagfin=0
  B1MINPHEX$=B1MINHEX$
  PAS_IND_NB=seqd\TDIF(ind_nb)
;   B1MIN+ seqd\TDIF(ind_nb) 
  B1MIN+ PAS_IND_NB 
 
  B1MINHEX$=_HHQ(B1MIN,"")

  ;;;*******************************************************************************************************************************************************************
  ;;; On peut anticiper la prochaine racine différente de celle actuelle (A+1)^2 =A^2+1+2A si A=SQR(X)=RAC donc (RAC^2)=X alors => (RAC+1)^2= (RAC^2)+1+2*RAC=X+1+(2*RAC)
  ;;; le mini de diff est 2 donc (A+2)^2 =A^2+4+4A si A=SQR(X)=RAC donc (RAC^2)=X alors => (RAC+2)^2= (RAC^2)+4+4*RAC=X+4+(4*RAC);;;*******************************************************************************************************************************************************************
  ;;; le mini de diff est D donc (A+D)^2 =A^2+D^2+2AD si A=SQR(X)=RAC donc (RAC^2)=X alors => (RAC+D)^2= (RAC^2)+D^2+2D*RAC=X+D^2+(2*D*RAC);;;*******************************************************************************************************************************************************************
  ;;; cette technique pose des pb pour les nombres premiers à trouver < au premier diviseur 
  If B1MIN =>B1MINRAC2 
    If B1MIN > SEQD\PREMDIV ;;;; Valeurs toujours <$7FFFFFFFFFFFFFFF;
  ; Il faudrait prendre le prochain diviseur dans le vecteur des différences avec la gestion de cet indice B2IND_MAXDIV essai en cours 
;     RAC2=DIF_MAXDIV*(2*B2MAXDIV+DIF_MAXDIV)
    RAC2=2*PAS_IND_NB* B2MAXDIV +(PAS_IND_NB*PAS_IND_NB)
    B1MINRAC2=B1MIN+RAC2
    B2MAXDIV.q=Sqr(B1MIN)+PAS_IND_NB+1
    ;     B1MINRAC2.Q=B1MIN+(4*B2MAXDIV)+4
   Else
    RAC2=4* B2MAXDIV +4
    B1MINRAC2=B1MIN+RAC2
    B2MAXDIV.q=Sqr(B1MIN)+2

  EndIf 
  EndIf
  
;   If B1MIN =>B1MINRAC2  ;;;; Valeurs toujours <$7FFFFFFFFFFFFFFF;;; avec pas mini de 2
;     RAC2=4* B2MAXDIV +4
;     B1MINRAC2=B1MIN+RAC2
;     B2MAXDIV.q=Sqr(B1MIN)+2
; ;     B1MINRAC2.Q=B1MIN+(4*B2MAXDIV)+4
;   EndIf  

  
  ;   IF B1MINRAC2>0
;     printn(_NL+_S(B1MINHEX$)+_s(MAXHEX$)+_n(B2MAXDIV)+_n(B1MINRAC2)+_n(FLAGFIN))
;   endif

  ; 	If B2DIVIS =>B2MAXDIV
  ; 	  
  ;   endif
  B2DIVIS=SEQD\PREMDIV 
  ind_nb+1
  ; 	if ind_nb>SEQD\NBSEQ-1
  If ind_nb>NBSEQ_1
    ind_nb=0  ;;; remise à zéro si le cycle des différences est atteint pour incrémentation des nombres susceptibles d'être premiers
  EndIf  
;       printn(_NL+_S(B1MINHEX$)+_s(MAXHEX$)+_n(B2MAXDIV)+_s(result$)+_n(FLAGFIN)+_n(CENTM)+_n(CENT))
;       PrintN(_NL+_S(B1MINHEX$)+_s(MAXHEX$)+_n(B2MAXDIV)+_n(B1MINRAC2)+_n(B2PAS)+_n(FLAGFIN))
  If B1MINHEX$<B1MINPhex$
;         printn(_NL+_s(B1MINHEX$)+_s(MAXhex$)+_n(B2MAXDIV))
    B1MINHEX$=MAXHEX$
  EndIf
;   paspas=seqd\TDIF(ind_nb)
;     printn(_s(B1MINHEX$)+_s(MAXhex$)+_n(B2MAXDIV)+_n(paspas))
Until B1MINHEX$=>MAXHEX$ ;;; Or B1MIN<0 ;;Si vous n'allez pas aux confins de la machine =$7FFFFFFFFFFFFFFF ;;; = 9223372036854775807 valeur max positive en ..q. 
 ;;                        Vous pouvez retirer (or B1MIN<0) ou dépassement de $7FFFFFFFFFFFFFFF
 ;;;;***********************************************************************************************************************************************************
 ;;;; ***********************************************  FIN DE LA PREMIERE  BOUCLE DES Nb à TESTER **************************************************************
 ;;;; ***********************************************  FIN DE LA DEUXIEME  BOUCLE DES Nb à TESTER  *************************************************************
 ;;;;***********************************************************************************************************************************************************

PrintN(result$)
; PrintN( "Nombre Minimal = "+Str(INFOSAISIE\NBASE)+"  Nombre Maximal = "+Str(MAX))
PrintN( "Nombre Minimal = "+HEX2DEC(_HHQ(INFOSAISIE\NBASE,""))+"  Nombre Maximal = "+HEX2DEC(_HHQ(MAX,"")))
PrintN("Nombre d'éléments du vecteur =:"+Str(SEQD\NBSEQ)+"  temps de préparation ="+Str(delta_deb))

PrintN("Temps millisecondes ="+Str(ElapsedMilliseconds()-dep_time))
PrintN("Nombre de nb premiers ="+Str(NB_TOT_DIVIS)+"  Nb de divisions /miliseconde = "+StrD(NBDIVISIONE/(ElapsedMilliseconds()-dep_time)))
Resultat$=""
For K=1 To 4
  Select K
    Case 1
      resultat$="Termine PAR 1="+Str(TABTERMIN(1))
    Case 2
      resultat$+" PAR 3="+Str(TABTERMIN(2))
    Case 3
     resultat$+" PAR 7="+Str(TABTERMIN(3))
   Case 4
     resultat$+" PAR 9="+Str(TABTERMIN(4))
  EndSelect    
Next 
resultat$+ "  PAR 2 ET 5  ="+Str(TABTERMIN(0))
PrintN(resultat$)
PrintN("C'est fini")
Input() 
CloseConsole()

; ***************** Ci dessous les Nombres premiers pour les 1000 premiers nombres
; 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
; 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199
; 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293
; 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397
; 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499
; 503 509 521 523 541 547 557 563 569 571 577 587 593 599
; 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691
; 701 709 719 727 733 739 743 751 757 761 769 773 787 797
; 809 811 821 823 827 829 839 853 857 859 863 877 881 883 887
; 907 911 919 929 937 941 947 953 967 971 977 983 991 997
 

A+
Il est fort peu probable que les mêmes causes ne produisent pas les mêmes effets.(Einstein)
Et en logique positive cela donne.
Il est très fortement probable que les mêmes causes produisent les mêmes effets.
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Nombres premiers : vérification à plusieurs

Message par Ollivier »

Bonjour Papipp,

merci pour ces codes, ici, ça "gonfle" de données. Sur un petit X64, c'est paradoxal d'avoir posté mon code plus haut, qui est réglé au ralenti.

Tu indiques que ton 1er code est indispensable pour le exécuter le 2nd code. J'ai du mal à voir un détail dedans car les fenêtres de code sont petites.

Car, tu as raison : mathématiquement, il me semble aussi très difficile de chercher des nombres 1ers dans une zone arbitraire, sans recourir aux p-factorielles.

Les gaps (que tu appelles les "différences") récoltés dans le domaine d'une p-factorielle servent de masque. Mais, je crois que c'est en fin 2015, dans la (longue) discussion avec fweil, j'avais parlé d'un décalage de ce masque. Et j'avais évoqué les chenilles d'un char, pour visualiser le mouvement de ce décalage. Si on ne fait pas ce décalage, on se retrouve possiblement avec des nombres premiers qui sont considérés comme multiples, et vice-versa.

Ainsi, on peut donner un résultat, comme je peux dire l'exemple suivant :
Le 28 203 747 ième nombre premier est 537 092 411.

À coup sûr, tout le monde peut vérifier, et éventuellement me dire que j'ai raison. Mais, ça n'implique pas que ma liste de nombres premiers depuis 2 jusqu'à 537 092 411, est exacte : elle peut être fausse.

Un mauvais décalage du "masque" que l'on prépare préalablement interchange des places de nombres possiblement premiers avec des places de nombres multiples (et sournoisement vice-versa).

Pour résumer, on peut voir que je ne crible pas, et c'est ainsi que j'avais trouvé l'existence de ce décalage. Je vérifie par divisions seulement.

Comment apréhendes-tu ce décalage dans tes codes ? C'est ce détail que je n'arrive pas à trouver facilement. Est-ce la fonction SYNCHRO() ?
Est-ce la recherche de la racine suivante ? (Le décalage étant lié au carré du nombre choisi "pour" p-fact(choisi) multiplié (et modulé, comme la chenille d'un char ramène au début ce qui dépasse à la fin) par le rang K tel que le départ est K * p-fact(choisi) )
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Nombres premiers : vérification à plusieurs

Message par Ollivier »

Et comme "tout savoir, et rien donner" c'est pas cool :mrgreen:
et que j'avais "promis" une illustration sur les écart (ou "gaps" ou "différences") entre nombres 1ers successifs,

et grâce à l'aide de ArS,

voici l'image :
Image
PAPIPP
Messages : 534
Inscription : sam. 23/févr./2008 17:58

Re: Nombres premiers : vérification à plusieurs

Message par PAPIPP »

je ne sais pas copier correctement un fichier, avec des tableaux et des colonnes colorées, dans ce forum.

Voir la solution ci-dessous
A+
Dernière modification par PAPIPP le mer. 10/août/2022 9:28, modifié 1 fois.
Il est fort peu probable que les mêmes causes ne produisent pas les mêmes effets.(Einstein)
Et en logique positive cela donne.
Il est très fortement probable que les mêmes causes produisent les mêmes effets.
PAPIPP
Messages : 534
Inscription : sam. 23/févr./2008 17:58

Re: Nombres premiers : vérification à plusieurs

Message par PAPIPP »

J'ai réussi à transposer le fichier *.doc en *.jpeg

Image
Image
Image

C'est bien la procédure SYNCHRO() qui permet de savoir à quelle position dans la table on doit commencer.
L'explication est donnée dans le texte ci-dessus ou son résumé ci-dessous.

Principe de la procédure synchro()

Pour définir une zone il nous faut un point de départ et un point d'arrivée.
Seul le point de départ nous intéresse ici.
Ce que nous savons ou connaissons :
1) P_fact(x) le prg peut travailler avec l’une ou l’autre des tables des différences.
Or x est connu ainsi que la première colonne de la matrice d’origine qui est devenue fantôme ici car elle ne sert pas à calculer les nombres premiers.

2) Le numéro de la première colonne utile, est placé dans la table des différences (c'est le cas ici) mais on peut le recalculer)

3) Nous pouvons connaitre la colonne de la matrice fantôme du point de départ.
C’est le reste de la division du point de départ par p_fact(x).

4) Donc maintenant à partir de la table des différences et du numéro de la première colonne.
On peut reconstituer la première ligne de la matrice fantôme.
Et ainsi connaitre la colonne de la table des différences dont le numéro est juste supérieur au numéro de la colonne du point de départ.



A+
Il est fort peu probable que les mêmes causes ne produisent pas les mêmes effets.(Einstein)
Et en logique positive cela donne.
Il est très fortement probable que les mêmes causes produisent les mêmes effets.
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Nombres premiers : vérification à plusieurs

Message par Ollivier »

Salut PAPIPP,

je vais regarder ça de près quand j'ai le temps. Je vais en gagner en regardant ton travail. J'avais réussi déjà. Je voulais automatiser cette "synchro". Mais il y avait toujours un bug de pas grand chose qui venait se greffer : il fallait programmer manuellement pour être certain de son décalage, et les p-factorielles, ça grandit vite.

Le gain n'est pas en temps pour moi, mais en mémoire. Là, je ne parviens pas à descendre en-dessous de 300 mégaoctets pour la taille du fichier contenant tous les nombres premiers jusqu'à 4 milliards. Donc, merci pour le rappel pratique.

En prog, je suis sur une suite numérique complètement déconcertante. Je posterai le code. J'essaie de la compresser, mais les gaps entre premiers c'est comme un langage sans superflu. Ça tend basiquement à conjecturer ceci :

On a une règle 1 :
à partir de 2 inclu, il n'y a qu'une seule fois la différence de 1 entre 2 nombres premiers consécutifs, et c'est entre 2 et 3 inclus.

On a une règle 2 :
à partir de 3 inclu, il n'y a qu'une seule fois le couple de différences {+2; +2} entre 3 nombres premiers consécutifs, et c'est entre 3 et 7 inclus.

Je conjecture la règle 3 :
à partir de 5 inclu, il n'y a qu'une seule fois le triplet de couples de différences {+2; +4}, entre 7 nombres premiers consécutifs, et c'est entre 5 et 23.

J'ai aussi remarqué que le calcul de la formule de Riemann zeta(x) quand x = 2, c'est seulement par le crible d'Eratosthène qu'il est résolvable partiellement.

J'ai enfin remarqué (peut-être connais-tu ça, ailleurs que de mon origine écrite en 2015) que

(soit a et b, deux nombres premiers consécutifs)
On a :
primoFact(a) + [sumFusion(primoDiff(a)/2) - 1]*b = c

Et je conjecture que c est un (grand) nombre premier.

(avec primoDiff(7) = 4, etc...
et sumFusion(a) le nombre de ressources en demi-gaps (=primoDiff(x)/2) de la règle 3 (conjecture décrite plus haut) utilisées dans le gap (b - a)

C'est sumFusion(x) la suite numérique déconcertante dont je parle plus haut.

C'est une sorte de division tordue comme un théorème de Shadok qui a deux caractéristiques :
- on divise non pas par un nombre mais par un couple de nombres
- on doit prendre en compte le restant de la division précédente pour choisir le diviseur.

Exemple au pif (retenue nulle)

Code : Tout sélectionner

x   sumFusion(x)
1   1
2   division par retenue sollicitée nulle (résultat impossible)
3   2
4   3
5   division par retenue sollicitée nulle (résultat impossible)
6   4
7   5
8   division par retenue sollicitée nulle (résultat impossible)
9   6
10  7
11  division par retenue sollicitée nulle (résultat impossible)
12  8
13  9
etc...
Et bien, après 43 millions de nombres premiers non compressée et une mémoire saturée, je n'ai eu que des résultats possibles ! Pas une seule "division" impossible !! Déconcertant...
Répondre