Nous avons un nombre à virgule flottante r
entre 0 et 1 et un entier p
.
Trouvez la fraction d'entiers avec le plus petit dénominateur, qui se rapproche r
avec une p
précision d' au moins chiffres.
- Entrées:
r
(un nombre à virgule flottante) etp
(entier). - Sorties:
a
etb
entiers, oùa/b
(flottant) se rapprocher
jusqu'auxp
chiffres.b
est le plus petit entier positif possible.
Par exemple:
- si
r=0.14159265358979
etp=9
, - alors le résultat est
a=4687
etb=33102
, - parce que
4687/33102=0.1415926530119026
.
Toute solution doit fonctionner en théorie avec des types à précision arbitraire, mais les limitations causées par les types à précision fixe des implémentations n'ont pas d'importance.
La précision signifie le nombre de chiffres après " 0.
" dans r
. Ainsi, si r=0.0123
et p=3
, alors a/b
devrait commencer par 0.012
. Si les premiers p
chiffres de la partie fractionnaire de r
sont 0, un comportement non défini est acceptable.
Critères de victoire:
- L'algorithme algorithmiquement le plus rapide gagne. La vitesse est mesurée en O (p).
- S'il existe plusieurs algorithmes les plus rapides, le plus court l'emporte.
- Ma propre réponse est exclue de l'ensemble des gagnants possibles.
Ps la partie mathématique est en fait beaucoup plus facile qu'il n'y paraît, je vous suggère de lire ce post.
la source
padEnd
etmatch
? Vous ne pouvez pas simplementslice
chaque chaîne à la bonne longueur, puis les soustraire?padEnd
est utilisé pour le testcasef(0.001,2)
etf(0.3,2)
.(r,p)=>{for(a=0,b=1;`${a/b}`.slice(0,p+2)-`${r}`.slice(0,p+2);a/b<r?a++:b++);return[a,b]}
(pas entièrement joué au golf).Haskell , O (10 p ) dans le pire des cas
121119 octetsEssayez-le en ligne!
Enregistré 2 octets grâce à Laikoni
J'ai utilisé l'algorithme de /math/2432123/how-to-find-the-fraction-of-integers-with-the-smallest-denominator-matching-an-i .
À chaque étape, le nouvel intervalle représente la moitié de l'intervalle précédent. Ainsi, la taille de l'intervalle est
2**-n
, oùn
est l'étape actuelle. Quand2**-n < 10**-p
, nous sommes sûrs d'avoir la bonne approximation. Pourtant sin > 4*p
alors2**-n < 2**-(4*p) == 16**-p < 10**-p
. La conclusion est que l'algorithme l'estO(p)
.EDIT Comme l'a souligné orlp dans un commentaire, l'affirmation ci-dessus est fausse. Dans le pire des cas,
r = 1/10**p
(r= 1-1/10**p
est similaire), il y aura des10**p
étapes:1/2, 1/3, 1/4, ...
. Il y a une meilleure solution, mais je n'ai pas le temps pour l'instant de résoudre ce problème.la source
f=
et enregistrer deux octets avecz<-floor.(*10^p),u<-a+c,v<-b+d
.f=
sur TIO dans le code Haskell.-cpp
drapeau du compilateur et écriref=\
dans l'en-tête: Essayez-le en ligne!C, 473 octets (sans contexte), O (p), non concurrent
Cette solution utilise la partie mathématique détaillée dans cet excellent article. J'ai calculé uniquement
calc()
la taille de la réponse.la source