1

bon voila, en fait je dois faire un programme pour savoir si une division a une perdiode & partie irreguliere:
genre:
1/3 = 0.33333
la periode c 3
5/6=0.83333
irregularité: 8
periode 3

bon j'ai deja commencé un peu a reflechir (heu ca m'arrivetongue), et l'algo de base me semble etre:

division -> obtention du nieme chiffre apres la virgule.
-> Debut d'un posible periode | ou suite d'une possible periode.
-> debut de periode possible -> verification de la suite a la prochaine boucle
-> sinon on reboucle simplement
...

bon c vraiment simpliste, et je trouve pas ca top sad
qqn aurait il une autre id?

2

En effet, c'est simpliste, très lent et pas top.
Intuitivement, comme on connais au départ le numérateur et le dénominateur, je dirais que le plus rapide (algorithmiquement) est de déterminer le motif périodique de l'inverse du dénominateur.

Par exemple, 11/42 = 0.2 619047 619047 ... (irrégularité : 0.2 ; motif : 619047)
On prend 1/42 = 0.0 238095 238095 ... l'irrégularité s'étend jusqu'au même rang, et le motif a la même taille.
Je n'ai pas de démonstration mathématique de cette équivalence, ce n'est qu'intuitif : ce qui est sûr, c'est qu'entre 1/D et N/D, le motif fait la même taille, et que l'irrégularité de N/D ne peut pas aller plus loin que celle de 1/D (1 chiffre après la virgule dans l'exemple), mais peut-être la valeur de N peut-elle faire en sorte que le dernier chiffre de l'irrégularité colle avec le dernier chiffre du motif, ce qui déplace le motif d'un cran vers la gauche, je n'en sais rien du tout.
Je dirais que tant que N<D, l'irrégularité ne bouge pas, que pour D<N<10D, l'irrégularité s'arrête plus à gauche d'un chiffre, que pour 10D<N<100D, l'irrégularité s'arrête plus à gauche de deux chiffres, etc, mais ceci n'est qu'intuitif, je le répète.
Mais surtout, avant de faire ceci, il faut bien simplifier la fraction au maximum (9/42 = 3/14, donc on étudie 1/14).

Pour déterminer la taille du motif : d'abord, il faut diviser D le plus de fois possible par 2 et par 5 (en base 10=2*5), soit 42 => 21 dans notre exemple.
Puis on regarde si 99 est divisible par 21 (pas le peine de regarder pour 9), et si ça ne marche pas, on teste avec 999, puis 9999, jusqu'à 999999 qui est divisible par 21 (pour passer de n 9 à n+1 9, il suffit d'incrémenter, de multiplier par 10, et de décrémenter).
Or 999999 = 10^6 - 1 (il y a 6 fois le chiffre 9), donc le motif a une taille de 6.
Enfin, pour passer de D=42 à 21, on a divisé 1 fois par 2, et 0 fois 5, donc l'irrégularité va jusqu'à 1 chiffre après la virgule (attention, purement intuitif).
Si, pour passer de D à D' en divisant le plus possible par 2 et 5, on a divisé X fois par 2 et Y fois par 5, je dirais que l'irrégularité va jusqu'à sup(X;Y) chiffres après la virgule.

Si mon intuition mathématique se révèle exacte, la seule boucle algorithmique serait alors de déterminer combien il faut de 9 pour que 9...9 soit divisible par D' ...

@++
avatar
Je ne suis pas développeur Java : je suis artiste Java.
Ce que l’on conçoit bien s’énonce clairement, / Et le code pour l’écrire arrive aisément.
Hâtez-vous lentement ; toujours, avec méthode, / Vingt fois dans l’IDE travaillez votre code.
La perfection est atteinte, non pas lorsqu’il n’y a plus rien à ajouter, mais lorsqu’il n’y a plus rien à retirer.
You don't use science to show that you're right, you use science to become right.

3

Si tu recherches les valeurs exactes des parties régulières et irrégulières (et pas seulement leur taille), alors tu ne peux pas supposer le dénominateur égal à 1 (et de toute façon en général ça n'accélèra pas bcp de le supposer...) ; tu es obligé d'y aller à la barbare gni

Tout ce que tu as à faire, c'est calculer u[n+1]=(u[n]*10)%q, avec u[0]=p (on suppose p<q, ça simplifie les choses smile). On pose aussi v[n]=E((u[n]*10)/q). Alors il faut trouver les plus petits indices i<j tels que u[i]=u[j], et alors ce que tu recherches c'est v[0 .. i-1] et v[i .. j-1]. En gros, tu peux faire une bonne vieille liste des familles et une recherche brutale pour un truc en O(n^2), ou bien un arbre binaire de recherche en O(n.ln(n)).

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

4

[...]tu ne peux pas supposer le dénominateur égal à 1 [...]
Tu voulais dire le numérateur ?
Bah si, étudier 1/D permet de connaître la position de la limite irrégularité/motif (si mon intuition est bonne, avec l'histoire du sup(X;Y)) et la taille du motif (ça, par contre, c'est certain), puis on trouve la position de la limite pour N/D avec les tests N<D, D<N<10D, ... (toujours si mon intuition est bonne) (en fait, pas la peine de faire des tests, il sufit de décaler la limite vers la gauche de sup(0;1+E(log(N/D))) ...).
Bien sûr, dans le programme final, on peut toujours dire que la limite est située sup(X;Y)-sup(0;1+E(log(N/D))) chiffres à droite de la virgule, sans passer par 1/D, mais le passage par 1/D était surtout là pour montrer d'où venaient mes termes de décalage.
Enfin, une fois que l'on a la position de la limite et la taille du motif, il ne reste plus qu'à faire un 'masquage' sur la valeur réelle approchée de N/D calculée à la fin.

@++
avatar
Je ne suis pas développeur Java : je suis artiste Java.
Ce que l’on conçoit bien s’énonce clairement, / Et le code pour l’écrire arrive aisément.
Hâtez-vous lentement ; toujours, avec méthode, / Vingt fois dans l’IDE travaillez votre code.
La perfection est atteinte, non pas lorsqu’il n’y a plus rien à ajouter, mais lorsqu’il n’y a plus rien à retirer.
You don't use science to show that you're right, you use science to become right.

5

Oui, le numérateur picol Mais relis ma phrase :
Si tu recherches
les valeurs exactes des parties régulières et irrégulières (et pas seulement leur taille), alors tu ne peux pas supposer le numérateur égal à 1

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

6

Si n n'est divisible ni par 2 ni par 5, il n'y a pas d'irrégularité, et la longueur de la période de 1/n est le plus petit entier p tel que n divise 999....9 (p chiffres)



Quand n est en plus divisible par 2 ou 5, une irrégularité est ajoutée.
Les droits inaliénables du troll :
1) le droit d'avoir raison
2) le droit d'être péremptoire
3) le droit de ne pas lire
4) le droit de ne pas répondre
5) le droit d'être de mauvaise foi
6) Autant pour moi / Faignant / Vivent Tintin et Milou

7

En tout cas en creusant un peu mathématiquement, on doit largement simplifier le problème, et réduire l'algorithmie à pas grand chose...
Les droits inaliénables du troll :
1) le droit d'avoir raison
2) le droit d'être péremptoire
3) le droit de ne pas lire
4) le droit de ne pas répondre
5) le droit d'être de mauvaise foi
6) Autant pour moi / Faignant / Vivent Tintin et Milou

8

Et évidemment, un nombre à représentation décimale infinie a une période si et seulement s'il est rationnel.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

9

gol

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

10

1ere étape :
écrire le nombre rationnel sous la forme D/p, où D est un nombre décimal et p est un entier non multiple de 2 et de 5.
D s'écrit D=d*10^n, où d est un nombre entier non multiple de 10.


2eme étape :
faire la division euclidienne de d par p :
d = a*p+b avec b<p


Alors la partie irrégulière de D/p est exactement a*10^n.
Et la partie périodique est b*10^n/p.


3eme étape :
La longueur de la période est le plus petit q tel que p divise 10^q-1 = 999....9 (q chiffres).
Il faut faire la recherche systématique pour trouver ce q. Pour accélérer la recherche : on sait qu'en plus q est un diviseur de p-1.

Enfin, la période vaut (10^q-1)*b/q








Exemple : pour 5/14

D = 5/2 = 2.5 = 25*10^-1 ; d = 25 ; n = -1
p = 7

d = 3*7+4
a = 3
b = 4

La partie régulière est a*10^n = 0.3

p-1 = 6, dont les diviseurs sont 1, 2, 3 et 6
On teste :
7 ne divise pas 9
7 ne divise pas 99
7 ne divise pas 999
7 divise 999999

la période est de longueur 6, et elle vaut 4*999999/7 = 571428




Donc, finalement, 5/14 = 0.3 571428 571428 571428 .....
Les droits inaliénables du troll :
1) le droit d'avoir raison
2) le droit d'être péremptoire
3) le droit de ne pas lire
4) le droit de ne pas répondre
5) le droit d'être de mauvaise foi
6) Autant pour moi / Faignant / Vivent Tintin et Milou

11

écrire le nombre rationnel sous la forme D/p, où D est un nombre décimal et p est un nombre premier non multiple de 2 et de 5.

Et tu écris 1/21 comment comme ça? À mon avis, le mot "premier" est en trop là.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

12

Note : je vais réutiliser les notation des posts ./2 et ./4, reportez-vous-y donc si besoin est.
Pollux a écrit :
Mais relis ma phrase :
Si tu recherches
les valeurs exactes des parties régulières et irrégulières (et pas seulement leur taille), alors tu ne peux pas supposer le numérateur égal à 1
Certes, mais relis ma phrase :
Enfin, une fois que l'on a la position de la limite et la taille du motif, il ne reste plus qu'à faire un 'masquage' sur la valeur réelle approchée de N/D calculée à la fin.
Je ne sais pas si le terme de masquage et adapté et compréhensible, mais c'est le meilleur que j'aie trouvé, par comparaison avec les masques de bits utilisés en Asm (sauf que là, on masque des digits décimaux).
D'ailleurs, je me suis aperçu bien après avoir écrit ceci que le masquage était inutile, puisqu'il suffit de multiplier le motif de 1/D par N, et de faire la sommation de la partie qui reboucle si ça dépasse.
Euh ... je crois que là, je ne suis pas très clair, je vais reprendre l'exemple de N/D = 11/42 = 0.2 619047 619047 ... = 0.2 M M ... avec M le motif.
On a 1/D = 1/42 = 0.0 238095 238095 ... = 0.0 m m ... soit un motif m de taille 6 chiffres, valant 238095.
Or N*m = 11*238095 = 2619045 = 2 619045 : il y a 7 chiffres, soit 1 de trop, et en découpant à 6, on a les bouts 2 et 619045, d'où M = 2+619045 = 619047.
D'ailleurs, l'irrégularité de 1/D vaut 0.0, et en ajoutant le bout de N*m qui dépasse (soit 2), on retrouve bien une irrégularité de 0.2 (en se calant bien sûr à la limite irrégularité/motif, pas à la virgule).

Maintenant, pour trouver le motif de 1/D sans avoir à calculer la valeur approchée (auquel cas le masquage interviendrait ici), on utilise celui de 1/D'.
1/D' = 1/21 = 0. 047619 047619 ... = 0. m' m' ... il n'y a pas d'irrégularité puisque D' n'est plus divisible par 2 ou 5, soit X' = Y' = 0, et l'irrégularité va jusqu'à S'=sup(X';Y')=0 chiffre après la virgule (j'ai ajouté des primes à X, Y et S, puisque ce ne sont pas exactement les mêmes qu'avant, ce ne sont que les valeurs équivalentes, qui ici valent forcément 0, c'était juste pour rappeler un peu l'utilité de X et Y).
Dans 1/D = 1/42, l'irrégularité va jusqu'à S=sup(X;Y)=sup(1;0)=1 chiffre après la virgule, et il n'y a que des 0 dans cette partie irrégulière.
La taille du motif est de 6 puisque 21 divise 999999 = 10^6 - 1, et on a 999999/21 = (10^6 - 1) * 1/21 = 047619. 047619 047619 ... - 0. 047619 047619 ... = 047619 = m', soit le motif de 1/D'.
Or pour passer de D=42 à D'=21, on a divisé X=1 fois par 2 et Y=0 fois par 5, d'où un décalage de S=sup(X;Y)=1 de la limite pour 1/D = 1/42.
999999/42 * 10^S = 999999/(21*2^X*5^Y) * (2*5) = 999999/21 * 5 = 047619 * 5 = 238095 = m.
Soit m = 047619 * 5 = m' * 10^S / (2^X * 5^Y) = m' * 2^(S-X) * 5^(S-Y), sachant qu'au moins une des valeurs S-X et S-Y est nulle.

Notre vénérable Normalien a écrit :
Si n n'est divisible ni par 2 ni par 5, il n'y a pas d'irrégularité, et la longueur de la période de 1/n est le plus petit entier p tel que n divise 999....9 (p chiffres)

Quand n est en plus divisible par 2 ou 5, une irrégularité est ajoutée.
écrire le nombre rationnel sous la forme D/p, où D est un nombre décimal et p est un nombre premier non multiple de 2 et de 5.
Il semblerait donc que mon intuition sur le décalage valant S=sup(X;Y) se révèle exacte ...
• Ethaniel est tout fier grin !!!


Pour ta forme en D/p, c'est exactement ce que je fait avec mon D devenant D', sauf que ça me permet de continuer à travailler avec des valeurs entières.
Pour p, il est vrai que le mot premier est de trop ...
Il a aussi écrit :
p-1 = 6, dont les diviseurs sont 1, 2, 3 et 6
On teste :
7 ne divise pas 9
7 ne divise pas 99
7 ne divise pas 999 7 divise 999999
Sachant que c'est un algorithme destiné à tourner sur machine, et non à être fait à la main, je pense que la recherche des diviseurs de p-1 pour tester la divisibilité de 9...9 par p (c'est-à-dire mon D') a un coût trop important.
et si ça ne marche pas, faire quelque chose qui en C serait :T ++ ; T *= 10 ; T -- ;Autant commencer à T=9,Certes, on teste pour 9999 et 99999 alors qu'on sait mathématiquement que ça ne peut pas marcher, mais sur machine, le temps perdu sera négligeable par rapport à la recherche des diviseurs de p-1.


0^(E-S) ; // le motif est M // l'irrégularité est I
Voici donc quel serait mon algorithme en pseudo-code C :  // acquérir la valeur de N
  // acquérir la valeur de D

  Dp = D ;
  E = max ( 0, 1 + floor(log(N/D)) ) ;

  X = -1 ;
  while ( Dp != floor(Dp) )
  { Dp /= 2 ;
    X ++ ;
  }
  Dp *= 2 ;

  Y = -1 ;
  while ( Dp != floor(Dp) )
  { Dp /= 5 ;
    Y ++ ;
  }
  Dp *= 5 ;

  T = 9 ;
  while ( T/Dp != floor(T/Dp) )
  { T ++ ;
    T *= 10 ;
    T -- ;
  }
  mp = T/Dp ;

  S = max ( X, Y ) ;
  m = mp * 2^(S-X) * 5^(S-Y) ;

  M = N * m ;
  b = floor ( M / (T+1) ) ;
  M -= b * (T+1) ;
  M += b ;

  I = b * 1
Je ne sais pas si ceci est du vrai code C, je ne touche plus à ça depuis longtemps, et cet algorithme est de trop haut niveau pour être fait simplement en Asm.
En tout cas, c'est une mise en forme informatique de tout ce que j'ai essayé d'expliquer, avec des variables intermédiaires inutiles mais en rapport avec les étapes que j'ai décrites.
J'espère juste que mon autre intuition (celle sur le décalage de E) est toujours valable, mais j'ai l'impression que la méthode donnée par HIPPOPOTAME utilise le même postulat.

Voilà voilà, j'espère juste ne pas avoir raconté trop n'importe quoi !

@++
avatar
Je ne suis pas développeur Java : je suis artiste Java.
Ce que l’on conçoit bien s’énonce clairement, / Et le code pour l’écrire arrive aisément.
Hâtez-vous lentement ; toujours, avec méthode, / Vingt fois dans l’IDE travaillez votre code.
La perfection est atteinte, non pas lorsqu’il n’y a plus rien à ajouter, mais lorsqu’il n’y a plus rien à retirer.
You don't use science to show that you're right, you use science to become right.

13

À mon avis, le mot "premier" est en trop là.

En effet, inattention de ma part.
Il faut lire "entier non multiple de 2 ni de 5".
Les droits inaliénables du troll :
1) le droit d'avoir raison
2) le droit d'être péremptoire
3) le droit de ne pas lire
4) le droit de ne pas répondre
5) le droit d'être de mauvaise foi
6) Autant pour moi / Faignant / Vivent Tintin et Milou

14

Sachant que c'est un algorithme destiné à tourner sur machine, et non à être fait à la main, je pense que la recherche des diviseurs de p-1 pour tester la divisibilité de 9...9 par p (c'est-à-dire mon D') a un coût trop important.


Oui et non.

Si tu le fait en C, et que tu fais les divisions successives "à la main" dans ton programme, alors c'est inutile de tester si q | p-1.

En revanche, si c'est un langage de haut niveau comme du basic, et que tu testes complètement à chaque étape si p | 999..99, alors autant tester avant chaque opération si q | p-1. On gagne beaucoup de temps car p-1 est petit alors que 9999...99 est grand.
Les droits inaliénables du troll :
1) le droit d'avoir raison
2) le droit d'être péremptoire
3) le droit de ne pas lire
4) le droit de ne pas répondre
5) le droit d'être de mauvaise foi
6) Autant pour moi / Faignant / Vivent Tintin et Milou

15

merci

bon j'ai lu mais j'ai pas tout saisi sad
en particulier:
Si n n'est divisible ni par 2 ni par 5, il n'y a pas d'irrégularité, et la longueur de la période de 1/n est le plus petit entier p tel que n divise 999....9 (p chiffres)
Quand n est en plus divisible par 2 ou 5, une irrégularité est ajoutée.

16

D'ailleurs Hippo ton truc est faux pour p non premier. C'est q | phi(p) (et pas q | p-1) dans le cas général... Bref il faudrait aussi factoriser p pour faire le test, pas top.

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

17

Moui, je m'a vautré....hum
Bon, faut oublier ce q | p-1
Les droits inaliénables du troll :
1) le droit d'avoir raison
2) le droit d'être péremptoire
3) le droit de ne pas lire
4) le droit de ne pas répondre
5) le droit d'être de mauvaise foi
6) Autant pour moi / Faignant / Vivent Tintin et Milou

18

Bah non, ça reste vrai avec phi(p) : même si ça n'a pas une grande utilité en soi, ça permet de donner une borne à la complexité du truc (et d'ailleurs, ça prouve qu'on peut trouver un algo en o(sqrt(p)) pour calculer la longueur de la partie périodique).

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

19

au fait, comment on calcule phi(p) vite?
Les droits inaliénables du troll :
1) le droit d'avoir raison
2) le droit d'être péremptoire
3) le droit de ne pas lire
4) le droit de ne pas répondre
5) le droit d'être de mauvaise foi
6) Autant pour moi / Faignant / Vivent Tintin et Milou

20

On factorise p gni
Je ne vois pas tellement d'autre méthode, d'ailleurs c'est bien le pb du RSA.

Euh sinon tu n'aurais pas un équivalent de sup[k>=n](card{diviseurs de k}/sqrt(k)) ? J'ai l'impression que c'est un o(1), mais je ne saurais pas vraiment en dire plus.

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

21

(en fait ça doit être un O(1/ln(n)), mais je ne sais pas si c'est équivalent à ça ou pas)

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)