Pourquoi la division dans Ruby renvoie-t-elle un entier au lieu d'une valeur décimale?

256

Par exemple:

9 / 5  #=> 1

mais je m'y attendais 1.8. Comment obtenir le bon résultat décimal (non entier)? Pourquoi revient-il 1du tout?

ErwinM
la source
4
Notez que si vous utilisez réellement une méthode pour renvoyer cette valeur, vous n'avez pas besoin de l'affecter à une variable; def method; a - b/8; endretournerait simplement le résultat du calcul de la méthode, car la dernière expression dans un appel de méthode est la valeur de retour.
Phrogz

Réponses:

268

Il fait une division entière. Vous pouvez créer l'un des nombres a Floaten ajoutant .0:

9.0 / 5  #=> 1.8
9 / 5.0  #=> 1.8
vees
la source
10
Cela fonctionne mais la réponse to_f ci-dessous semble plus utile. Est-ce que to_f est plus idiomatique en Ruby?
notapatch
9
La .to_fréponse est meilleure si vous divisez deux variables contenant des entiers, par exemple a.to_f / b. Si vous divisez littéralement deux entiers codés en dur (ce qui est probablement étrange), l'utilisation 9.0 / 5est très bien.
jefflunt
350

Il fait une division entière. Vous pouvez utiliser to_fpour forcer les choses en mode virgule flottante:

9.to_f / 5  #=> 1.8
9 / 5.to_f  #=> 1.8

Cela fonctionne également si vos valeurs sont des variables plutôt que des littéraux. La conversion d'une valeur en un flottant est suffisante pour contraindre l'expression entière à l'arithmétique à virgule flottante.

mu est trop court
la source
1
C'est la réponse la plus "rails" que la réponse acceptée.
Sean Ryan
@muistooshort: je ne peux pas le reproduire, désolé. Je faisais probablement quelque chose de mal.
Joao Costa
4
@SeanRyan Pourquoi spécifiquement Rails plutôt que Ruby en général? Je ne vois pas pourquoi un développeur (Ruby on) Rails ferait cette chose spécifique différemment d'un développeur Ruby général. Peut-être que je suis juste sémantique et la plupart des gens voient juste (Ruby on) Rails et Ruby dans des cas comme celui-ci.
Chinoto Vokro
169

Il y a aussi la Numeric#fdivméthode que vous pouvez utiliser à la place:

9.fdiv(5)  #=> 1.8
Konrad Reiche
la source
1
C'est la méthode la plus rapide que j'ai testée, la seule façon d'obtenir plus de performances est de diviser les opérandes qui sont des flottants pour commencer. J'ai construit un générateur de nombres premiers dans Ruby afin d'apprendre la syntaxe, maintenant je l'optimise pour savoir ce qui fonctionne le mieux. Voici l'Indice de référence mis en place: require 'base64'; require 'zlib', met Zlib.inflate (Base64.decode64 ( "eJxlkMEOwiAQRO98hekFuGzxQEwPXvwR01ZqiYHqBk2Tln8XDlWgnDbM25nJonq9NaoD7ZTtR9PigxK09zM7AkgRHieXTYHOsBNf1nklM6B6TuhYpdp + rPgSdiCOi / d / kQ71QBOtAVFLEDly05 + UYQ2H + MckL6z0zioDdJG1S9K1K4iQAW66DhnmiqRYKEJFXMByux + XuOJ2XdO60dKsjC7aBtyTL5O5hLk ="))
Chinoto Vokro
Une question, préserverait-elle la précision comme si nous utilisions «décimal»?
Adam Aiken
39

Vous pouvez le vérifier avec irb:

$ irb
>> 2 / 3
=> 0
>> 2.to_f / 3
=> 0.666666666666667
>> 2 / 3.to_f
=> 0.666666666666667
Renaud
la source
26

Vous pouvez inclure le mathnmodule ruby .

require 'mathn'

De cette façon, vous allez pouvoir faire la division normalement.

1/2              #=> (1/2)
(1/2) ** 3       #=> (1/8)
1/3*3            #=> 1
Math.sin(1/2)    #=> 0.479425538604203

De cette façon, vous obtenez la division exacte (classe Rational) jusqu'à ce que vous décidiez d'appliquer une opération qui ne peut pas être exprimée comme rationnelle, par exemple Math.sin.

Rok Kralj
la source
1
Le module mathn est obsolète depuis ruby ​​2.2
Meier
11

Remplacez 5par 5.0. Vous obtenez une division entière.

Tyler Eaves
la source
6

Fixnum # to_r n'est pas mentionné ici, il a été introduit depuis ruby ​​1.9. Il convertit Fixnum en forme rationnelle. Voici des exemples de ses utilisations. Cela peut également donner une division exacte tant que tous les nombres utilisés sont Fixnum.

 a = 1.to_r  #=> (1/1) 
 a = 10.to_r #=> (10/1) 
 a = a / 3   #=> (10/3) 
 a = a * 3   #=> (10/1) 
 a.to_f      #=> 10.0

Exemple où un flotteur opéré sur un nombre rationnel couvre le résultat à flotter.

a = 5.to_r   #=> (5/1) 
a = a * 5.0  #=> 25.0 
ucpuzz
la source