10
votes

Vérifiez si un nombre est rationnel en Python, pour une précision FP donnée

J'aimerais connaître une bonne façon de vérifier si un numéro X est un rationnel (deux entiers n, m existent de sorte que x = n / m) en python.

in mathematica, cela se fait par la fonction rationaliser [6.75] : 27/4

Je suppose que cette question a une réponse pour une précision donnée. Y a-t-il un algorithme commun d'obtenir ces deux entiers?


0 commentaires

7 Réponses :


4
votes

Peut-être que cela vous intéressera: meilleure approximation rationnelle


0 commentaires

6
votes

Tout nombre avec une expansion décimale finie est un nombre rationnel. Vous pouvez toujours résoudre par exemple xxx

en disant qu'il correspond à xxx

de sorte que des flotteurs et des doubles ont une précision finie qu'ils sont tous rationnels.


1 commentaires

Notez «Précision donnée» dans la question initiale.



1
votes

Comme vous avez noté que tout numéro de point flottant peut être converti en nombre rationnel en déplaçant le point décimal et en divisant par la puissance appropriée de dix.

Vous pouvez ensuite retirer le plus grand diviseur commun du dividende et diviseur et vérifiez si ces deux numéros correspondent au type de données de votre choix.


1 commentaires

FWIW, vous pouvez déterminer facilement déterminer le plus grand diviseur commun en Python en utilisant fractions.gcd () .



17
votes

in python> = 2.6 Il y a un as_integer_ratio méthode sur des flotteurs: xxx

Cependant, en raison de la manière dont les flotteurs sont définis dans les langages de programmation Il n'y a pas de numéros irrationnels .


4 commentaires

Les irrationnelles ne peuvent pas être représentées par le ratio (NAL) S non plus - que la définition même et la source du nom!


@delnan, FWIW, ils peuvent être représentés comme des rationnels. Les deux méthodes d'utilisation courante pour le faire officiellement (DEDEKIND CUTS et CAUCHY SERIES) utilisent des rationnelles pour le faire. Ils utilisent juste une quantité infinie de rationnelles :)


Pour un vrai plaisir, recherchez des fractions continues. Pour mettre en œuvre une solution vous-même, vous effectuez la fraction continue jusqu'à ce qu'il entraîne une fraction exacte ou que le dénominateur devient trop gros pour votre goût.


Ensuite, pour voir si c'était rationnel, faites une vérification sanité définie par l'utilisateur sur votre dénominateur.



4
votes

Python utilise une représentation à virgule flottante plutôt que des nombres rationnels. Jetez un coup d'œil à La bibliothèque standard fractions module pour certains détails À propos des chiffres rationnels.

Observez, par exemple, cela, pour voir pourquoi cela va mal: xxx

(Oh, vous voulez voir un cas où cela fonctionne?) xxx


3 commentaires

Y a-t-il des langages de programmation qui "utilisent" des chiffres rationnels?


@SilentGhost: ABC fait. Voir les expériences de Guido avec et pourquoi Python ne le fait pas: python-history.blogspot.com/2009/03/...


@SilentGhost, commune Lisp et (je crois) le schéma fait aussi.



0
votes

Le problème avec des nombres réels dans les langages de programmation est qu'ils sont généralement définis comme des fonctions qui renvoient une représentation finie donnée une précision (par exemple, une fonction qui prend N comme argument et renvoie un numéro de point flottant dans une précision de 2 ^ -n) .

Vous pouvez définitivement transformer un élément rationnel / entier en une réelle réelle, mais même la comparaison des réels d'égalité est indéchée (c'est essentiellement le problème d'arrêt).

Vous ne pouvez pas dire si un nombre réel X est rationnel: même en mathématiques, il est généralement difficile, car vous devez trouver p et q tel que x = p / q, et cela est souvent non constructif.

Cependant, étant donné une fenêtre de précision, vous pouvez trouver la "meilleure" approximation rationnelle pour cette précision en utilisant par exemple une expansion de fraction continue. Je crois que c'est essentiellement ce que fait Mathematica. Mais dans votre exemple, 6,75 est déjà rationnel. Essayez avec pi à la place.


0 commentaires

10
votes

La nature des nombres de points flottants signifie qu'il n'a aucun sens pour vérifier si un numéro de point flottant est rationnel, car tous les nombres à virgule flottante sont vraiment des fractions de la forme n / 2 e . Cependant, vous voudrez peut-être savoir s'il existe une fraction simple (une avec un petit dénominateur plutôt qu'une grande puissance de 2) qui se rapproche étroitement d'un numéro de point flottant donné.

Donald Knuth discute de ce dernier problème dans l'art de la programmation informatique volume II. Voir la réponse à l'exercice 4.53-39. L'idée est de rechercher la fraction avec le dénominateur le plus bas dans une plage, en élargissant les points de terminaison de la gamme comme des fractions continues tant que leurs coefficients sont égaux, puis lorsqu'ils diffèrent, prenez la valeur la plus simple. Voici une implémentation assez simple en python: xxx

et voici quelques résultats: xxx


3 commentaires

+1 pour fournir l'algorithme. Nitpick: il devrait être "si x == y: retourne x" puisque vous semblez envisager l'intervalle fermé [x, y].


Je ne fais pas cela car x et y sont censés être des flotteurs pendant que la fonction est censée renvoyer une fraction . Je pense qu'il est préférable d'augmenter une erreur dans ce cas.


Il serait logique de renvoyer fraction (* x.as_integer_ratio ()) , je suppose.