Bonsoir,
Je veux générer un grand nombre X compris entre N1 et N2.
Comment procéder avec la fonction RandomGInt ?
Merci pour votre aide.
Cordialement
Fermat
Version imprimable
Bonsoir,
Je veux générer un grand nombre X compris entre N1 et N2.
Comment procéder avec la fonction RandomGInt ?
Merci pour votre aide.
Cordialement
Fermat
Bonjour,
Le principe X := N1 + RandomGInt(N2 - N1); à adapter avec les fonctions d'addition et de soustraction de l'unité...
Bonjour,
Par définition, je suis l'auteur de l'unité UnitGint, à moins qu'il s'agisse d'autre chose (??...)
La solution proposée par Ph.B est très judicieuse.
Il y est ainsi possible de générer des aléatoires de plusieurs types :
Code:
1
2
3
4
5
6
7
8
9
10
11 // Génère un GInt aléatoire situé dans le domaine [#0...Nb] function FRandomGInt(Nb : GInt): GInt; // Génère un GInt aléatoire de NbBits +- 8 function FRandomLGInt(NbBits : longword): GInt; // Génère un GInt aléatoire de NbBits +- 8 tous les octets impairs function FRandomLGIntImpair(NbBits : longword): GInt; // Génère un GInt aléatoire de NbBits Premier function FGetGIntPrime(NbBits : longword): GInt; // Génère un GInt premier aléatoire sous la formule de Dirichlet // Nb = a^2 + b avec b Impair function FDirichlet(NbBits : longword): GInt;
Bonsoir,
Je vous remercie de votre réponse.
Je vais étudier la documentation de 'NewGInt & NewGCent'.
Cordialement
Fermat
Pas de problème, c'est moi qui vous remercie de pratiquer avec mes unités... De mon côté, je suis en cogitation pour établir une routine qui donne directement le GInt voulu dans le domaine [N1..N2]. Dès qu'elle est au point, je la placerai ici dans cette discussion..
N.B. Important : Pour la génération des valeurs aléatoires, la NewGInt n'utilise pas le générateur de Delphi, mais un en interne qui lui est propre donc indépendant. Cela suppose que pour tout appel d'aléatoire, il faut au moins une fois faire un appel préalable à la procédure d'initialisation de ce générateur : PRndGIntMize.
Bonsoir,
Merci de votre attention.
Vos conseils sont les bienvenus, car j'ai tant à apprendre.
Cordialement.
Fermat
re,
En étudiant la documentation de :
"Fonctions et procédures de NewGCENT.pas",un exemple concret pour chaque fonction,et procedure,me serait bien utile.
Merci
Fermat
Comme promis, voici la fonction qui permet d'avoir un GInt aléatoire (pseudo) dans le domaine [nb1..nb2], quelles que soient les bornes GInt données par Nb1 et Nb2 :
Bien sûr à utiliser avec (ou mieux intégrer à) NewGIntCode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 // Génère un GInt aléatoire situé dans le domaine [Nb1..Nb2] function FRandomDGInt(Nb1,Nb2: GInt): GInt; register; var i : integer; Nb: GInt; begin i:=IsCompGInt(Nb1,Nb2); if i<0 then begin // Nb1<Nb2 Nb:=FRandomGInt(FSubGInt(Nb2,Nb1)); Nb:=FAddGInt(Nb1,Nb); end; if i>0 then begin //Nb1>Nb2 Nb:=FRandomGInt(FSubGInt(Nb1,Nb2)); Nb:=FAddGInt(Nb2,Nb); end; if i=0 then Nb:=FCopyGInt(Nb1); //Nb1=Nb2 Result:=Nb; end;
Un petit exemple d'utilisation :
Code:
1
2
3
4
5
6
7
8
9
10
11 procedure TForm1.Button1Click(Sender: TObject); var Nb, Nb1, Nb2 : GInt; i: integer; begin PRndGIntMize; i:=64; Nb1:=FRandomLGInt(i); Nb2:=FRandomLGInt(i+64); Nb:= FRandomDGInt(Nb1,Nb2); ShowMessage(' Nb1: '+FGIntToStr(Nb1)+#10 +' Nb : '+FGintToStr(Nb) +#10 +' Nb2: '+FGIntToStr(Nb2)); end;
HOU LA ! Je risque d'y passer toutes mes nuits... Le mieux serait d'expliquer quelques parties de ce que tu projettes de faire afin que je puisse te donner les pistes d'élaboration.Citation:
En étudiant la documentation de :
"Fonctions et procédures de NewGCENT.pas",un exemple concret pour chaque fonction,et procedure,me serait bien utile.
L'unité NewGCent a été conçue pour avoir une vitesse exceptionnelle des conversions pour affichages des grands nombres, ce que mon collègue et co-auteur Gilbert Geyer a très bien su mettre à profit dans son programme de calculette scientifique .
Cependant, cette unité pour manipuler des très grands nombres entiers n'est pas aussi rationnelle que la NewGInt car elle utilise plus de RAM pour les calculs et elle n'est pas aussi complète en fonctions et procédures. L'utilisation de l'une plutôt que de l'autre (ou les deux) relève des besoins du programme à développer.
Bonjour René,
Tu dis "L'unité NewGCent a été conçue pour ... n'est pas aussi rationnelle que la NewGInt" :
Entièrement d'accord, sauf pour le cas particulier des Factorielles qui à partir de Factorielle(5) se terminent toutes par un ou beaucoup de zéros, de même que pour tout calcul avec des nombres qui se terminent par une flopée de zéros, ce qui fait que les zéros d'un GCent en s'accumulant dans l'exposant raccourcissent la longueur de la string des chiffres significatifs alors que dans le cas d'un Gint la longueur de la string n'est pas raccourcie si le nombre décompressé contient beaucoup de zéros terminaux.
Exemple FactorielleGR(12300000) = 486784890931952525434295971392334244882507805463549E81863964 (mis 40 secondes).
alors qu'avec les GInt au delà de Factorielle(12300) j'ai le message "mémoire insuffisante" avec Calculator.exe
Par contre, comme dans la vie courante on ne manipule que très rarement des grands nombres, je suis curieux de savoir dans quel type d'application Fermat les utilise : calculs d'astronomie ? Autres ?
A+. :D
EDIT : Oups dans la précipitation j'ai écrit la bêtise suivante "ce qui fait que les zéros d'un GCent en s'accumulant dans l'exposant raccourcissent la longueur de la string des chiffres significatifs" : En fait la principale différence entre un Gint et un GCent est que le GInt est une string codée en base 256 alors que le GCent est une string codée en base 100 et fans laquelle il est beaucoup plus facile de détecter la présence de zéros terminaux, et cette particularité a permis de créer l'unité unit UnitGR utilisée pour des calculs avec des Grands Réels à nombre de chiffres significatifs supérieur à 20 par la calculette dont le code est téléchargeable via le lien cité par REKIN85.
Dans cette UnitGR les nombres sont stockés dans le type tGRsuivant :
Et ce type permet donc de transférer les zéros terminaux du GCent "Sv" dans l'exposant "Expo" au fur et à mesure de leur apparition et de raccourcir d'autant la longueur de la string "Sv".Code:
1
2
3
4
5
6
7
8
9
10
11
12 type tGR = record Signe : ShortString; Sv : GCent; // chaîne numérique représentée en base 100 expurgée des puissances de 10 Expo : Int64; // Expo correspond aux puissances de 10 mais renseigne aussi sur la position du DecimalSeparator // dans la représentation décimale après conversion du nombre : // - si Expo < 0 alors Expo = Décalage du Séparateur Décimal par rapport à la fin de la chaîne Sv // - si Expo = 0 alors Sv = valeur entière // - si Expo > 0 alors Sv = valeur entière et Expo équivaut au nombre de '0' à ajouter en fin de Sv // dans une représentation intégrale du nombre (représentation au format non scientifique) end; var nbCsGr : int64; //<- nombre de Chiffres significatifs souhaités lors des calculs. Ce nombre correspond à celui de la représentation décimale d'une valeur (hors Exposant)
En complément à ceci, la var nbCsGr permet elle aussi de limiter la longueur de la string "Sv".
La longueur de la string "Sv" étant ainsi réduite au minimum utile, ceci a comme double conséquence d'accélérer la vitesse d'exécution et de réduire les besoins en espace-mémoire.
Bonjour Gilbert,
NewGCent est aussi idéale pour les caractères de divisibilité des entiers en base décimale... Finalement comme il existe des passerelles pour convertir les GCent en GInt et vice et versa, on peut à très bon escient se servir des deux unités si besoin; on en a très bien fait l'expérience tous deux...
Calculator a été volontairement bridé sur certaines opérations (exponentielle, factorielle, générateurs...) très gourmandes en RAM pour éviter les plantages rédhibitoires. Ce petit programme n'a été élaboré que pour illustrer l'utilisation de NewGInt; il n'était pas question de lui faire avaler trop d'élucubrations opératoires...
Je suis d'accord avec toi, il serait intéressant de savoir à quel domaine fermat compte utiliser ces unités.
Bonsoir,
Je vous remercie pour votre collaboration très active.
En testant votre exemple,j'ai le message:
Fichier non trouvé"UnitGInt.dcu"
Merci
Fermat
Bonsoir,
Désolé,c'est un oubli de ma part.
Fermat
Bonjour,
Comme j'ai écrit une bêtise dans mon message précédent je lui ai ajouté un EDIT correctif concernant l'utilisation des GCent.
Oui, on aimerait bien savoir. :ptdr:Citation:
Rekin85 : Je suis d'accord avec toi, il serait intéressant de savoir à quel domaine fermat compte utiliser ces unités.
A+. :D
fermat a écrit :
Bonjour. Je tiens à repréciser que UnitGInt et NewGInt ne sont absolument pas compatibles même si elles utilisent les mêmes concepts des grands entiers en Ansistring. Pour éviter les embrouilles, toutes les procedures et functions ont été dénommées différemment.Citation:
Je vous remercie pour votre collaboration très active.
En testant votre exemple,j'ai le message:
Fichier non trouvé"UnitGInt.dcu"
Donc : si on utilise NewGint, cette dernière n'avalera pas les appels de fonctions d'UnitGInt. Une seule règle, ne pas les faire cohabiter et utiliser les dénominations ad hoc.
Ces messages m'ont fait penser que la fonction dont fermat a ressenti le besoin serait finalement une routine très importante pour générer un GInt aléatoire (pseudo) dans un domaine bien borné par 2 GInt. En définitive, je me suis dit que la fonction :
Function FRandomDGInt(Nb1,Nb2: GInt): GInt;
méritait bien de figurer en bonne place dans l'unité NewGInt comme routine de base très importante. Je me suis mis en demeure de cogiter une routine optimisée et sans déboire que voici :
Evidemment il faudra penser à sa déclaration en partie interface de l'unité pour qu'elle soit accessible depuis un programme appelant.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 // Génère un GInt aléatoire situé dans le domaine [Nb1..Nb2] function FRandomDGInt(Nb1,Nb2: GInt): GInt; register; var ln1,ln2,ln3: longWord; asm push esi // Pointeur Nb1 push edi // Pointeur Nb2 push ebx // Pointeur Nb3 push ecx // Réserve Result mov esi,eax mov eax,[esi]-$4 mov edi,edx mov edx,[edi]-$4 call Compare // compare Nb1 à Nb2 test eax,eax jnz @Nb1Nb2 // Cas où Nb1=Nb2 mov edi,ebx mov eax,edx Call System.@NewAnsiString mov edi,eax mov eax,edx call CopyEsiToEdi mov ebx,edi jmp @Fin // Cas où Nb1<>Nb2 @Nb1Nb2: jg @Sup // si eax négatif xchg esi,edi // on échange pour que Nb1>Nb2 @Sup: mov eax,[esi]-$4 mov ln1,eax mov edx,[edi]-$4 mov ln2,edx sub eax,edx call RandDw add eax,ln2 mov ln3,eax call System.@NewAnsistring mov ebx,eax // Remplisszage Result @RMake: mov ecx,ln3 add ebx,ecx xor eax,eax @RR: dec ebx mov al,$FF call RandDW mov byte ptr[ebx],al loop @RR // Validation Resultat @Valide1: // Nb3<Nb1 mov eax,esi mov edx,ebx call IsCompGInt test eax,eax jl @RMake @Valide2: // Nb3>Nb2 mov eax,ebx mov edx,edi call IsCompGInt jl @RMake @Fin: pop eax call System.@LStrClr mov [eax],ebx pop ebx pop edi pop esi end;