¿Por qué la división en Ruby devuelve un número entero en lugar de un valor decimal?

256

Por ejemplo:

9 / 5  #=> 1

pero esperaba 1.8. ¿Cómo puedo obtener el resultado decimal (no entero) correcto? ¿Por qué está volviendo 1en absoluto?

ErwinM
fuente
44
Tenga en cuenta que si realmente está utilizando un método para devolver este valor, no necesita asignarlo a una variable; simplemente def method; a - b/8; enddevolvería el resultado del cálculo del método, ya que la última expresión en una llamada al método es el valor de retorno.
Phrogz

Respuestas:

268

Está haciendo división entera. Puede hacer uno de los números a Floatsumando .0:

9.0 / 5  #=> 1.8
9 / 5.0  #=> 1.8
vees
fuente
10
Esto funciona, pero la respuesta to_f a continuación parece más útil. ¿Es demasiado idiomático en Ruby?
notapatch
9
La .to_frespuesta es mejor si está dividiendo dos variables que contienen enteros, por ejemplo a.to_f / b. Si literalmente está dividiendo dos enteros codificados (lo que probablemente sea extraño), entonces usar 9.0 / 5está bien.
jefflunt
350

Está haciendo división entera. Puede usar to_fpara forzar cosas al modo de punto flotante:

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

Esto también funciona si sus valores son variables en lugar de literales. Convertir un valor en un flotante es suficiente para obligar a la expresión completa a la aritmética de coma flotante.

mu es demasiado corto
fuente
1
Esta es la respuesta más "carriles" que la respuesta aceptada.
Sean Ryan
@muistooshort: no puedo replicarlo, lo siento. Probablemente estaba haciendo algo mal.
Joao Costa
44
@SeanRyan ¿Por qué específicamente Rails en lugar de Ruby en general? No veo por qué un desarrollador de (Ruby on) Rails haría esta cosa específica de manera diferente a un desarrollador general de Ruby. Tal vez solo estoy criticando la semántica y la mayoría de la gente solo ve (Ruby on) Rails y Ruby como sinónimos en casos como este.
Chinoto Vokro
169

También existe el Numeric#fdivmétodo que puede utilizar en su lugar:

9.fdiv(5)  #=> 1.8
Konrad Reiche
fuente
1
Este es el método más rápido que probé, la única forma de obtener más rendimiento es dividir los operandos que son flotadores para empezar. He construido un generador de números primos en Ruby para aprender la sintaxis, ahora lo estoy optimizando para saber qué funciona mejor. Aquí está el punto de referencia que arme: require '' base 64; require 'zlib'; pone Zlib.inflate (Base64.decode64 ( "eJxlkMEOwiAQRO98hekFuGzxQEwPXvwR01ZqiYHqBk2Tln8XDlWgnDbM25nJonq9NaoD7ZTtR9PigxK09zM7AkgRHieXTYHOsBNf1nklM6B6TuhYpdp + rPgSdiCOi / d / kQ71QBOtAVFLEDly05 + + UYQ2H MckL6z0zioDdJG1S9K1K4iQAW66DhnmiqRYKEJFXMByux + XuOJ2XdO60dKsjC7aBtyTL5O5hLk ="))
Chinoto Vokro
Una pregunta, ¿conservaría la precisión como si estuviéramos usando 'decimal'?
Adam Aiken
39

Puedes consultarlo con irb:

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

Puede incluir el mathnmódulo ruby .

require 'mathn'

De esta manera, podrás hacer la división normalmente.

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

De esta manera, obtienes una división exacta (clase Racional) hasta que decides aplicar una operación que no puede expresarse como racional, por ejemplo Math.sin.

Rok Kralj
fuente
1
El módulo matemático está en desuso desde ruby ​​2.2
Meier
11

Cambiar el 5a 5.0. Estás obteniendo división entera.

Aleros Tyler
fuente
6

El Fixnum # to_r no se menciona aquí, se introdujo desde ruby ​​1.9. Convierte Fixnum en forma racional. A continuación se presentan ejemplos de sus usos. Esto también puede dar una división exacta siempre que todos los números utilizados sean 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

Ejemplo donde un flotador operado en un número racional convierte el resultado en flotador.

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