Warum gibt die Division in Ruby eine Ganzzahl anstelle eines Dezimalwerts zurück?


256

Beispielsweise:

9 / 5  #=> 1

aber ich habe erwartet 1.8. Wie kann ich das richtige Dezimalergebnis (nicht ganzzahlig) erhalten? Warum kehrt es 1überhaupt zurück?


4
Beachten Sie, dass Sie diesen Wert keiner Variablen zuweisen müssen, wenn Sie ihn tatsächlich mit einer Methode zurückgeben. def method; a - b/8; endwürde einfach das Ergebnis der Berechnung von der Methode zurückgeben, da der letzte Ausdruck in einem Methodenaufruf der Rückgabewert ist.
Phrogz

Antworten:


268

Es macht eine ganzzahlige Division. Sie können eine der Zahlen a machen, Floatindem Sie Folgendes hinzufügen .0:

9.0 / 5  #=> 1.8
9 / 5.0  #=> 1.8

10
Dies funktioniert, aber die Antwort to_f unten scheint nützlicher zu sein. Ist to_f in Ruby idiomatischer?
Notapatch

9
Die .to_fAntwort ist besser, wenn Sie zwei Variablen teilen, die Ganzzahlen enthalten, z a.to_f / b. Wenn Sie buchstäblich zwei fest codierte Ganzzahlen teilen (was wahrscheinlich seltsam ist), ist die Verwendung 9.0 / 5in Ordnung.
Jefflunt

350

Es macht eine ganzzahlige Division. Sie können verwenden to_f, um Dinge in den Gleitkommamodus zu zwingen:

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

Dies funktioniert auch, wenn Ihre Werte Variablen anstelle von Literalen sind. Das Konvertieren eines Werts in ein Gleitkomma reicht aus, um den gesamten Ausdruck in Gleitkomma-Arithmetik zu zwingen.


1
Dies ist die Antwort "mehr Schienen" als die akzeptierte Antwort.
Sean Ryan

@ Muistooshort: Ich kann es nicht replizieren, sorry. Ich habe wahrscheinlich etwas falsch gemacht.
Joao Costa

4
@ SeanRyan Warum speziell Rails statt Ruby im Allgemeinen? Ich verstehe nicht, warum ein (Ruby on) Rails-Entwickler diese spezielle Sache anders machen würde als ein allgemeiner Ruby-Entwickler. Vielleicht wähle ich nur die Semantik aus und die meisten Leute sehen (Ruby on) Rails und Ruby in solchen Fällen auch als synonym.
Chinoto Vokro

169

Es gibt auch die Numeric#fdivMethode, die Sie stattdessen verwenden können:

9.fdiv(5)  #=> 1.8

1
Dies ist die schnellste Methode, die ich getestet habe. Die einzige Möglichkeit, mehr Leistung zu erzielen, besteht darin, Operanden zu teilen, die zunächst Floats sind. Ich habe in Ruby einen Primzahlengenerator erstellt, um die Syntax zu lernen. Jetzt optimiere ich ihn, um herauszufinden, was am besten funktioniert. Hier ist die Benchmark ich zusammen: require 'base64'; require 'zlib'; Puts Zlib.inflate (Base64.decode64 ( "eJxlkMEOwiAQRO98hekFuGzxQEwPXvwR01ZqiYHqBk2Tln8XDlWgnDbM25nJonq9NaoD7ZTtR9PigxK09zM7AkgRHieXTYHOsBNf1nklM6B6TuhYpdp + rPgSdiCOi / d / kQ71QBOtAVFLEDly05 + UYQ2H + MckL6z0zioDdJG1S9K1K4iQAW66DhnmiqRYKEJFXMByux + XuOJ2XdO60dKsjC7aBtyTL5O5hLk ="))
Chinoto Vokro

Eine Frage, würde es die Genauigkeit bewahren, wie wir 'Dezimal' verwenden?
Adam Aiken

39

Sie können es mit irb überprüfen:

$ irb
>> 2 / 3
=> 0
>> 2.to_f / 3
=> 0.666666666666667
>> 2 / 3.to_f
=> 0.666666666666667

26

Sie können das Ruby- mathnModul einschließen .

require 'mathn'

Auf diese Weise können Sie die Aufteilung normal vornehmen.

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

Auf diese Weise erhalten Sie eine exakte Division (Klasse Rational), bis Sie sich entscheiden, eine Operation anzuwenden, die beispielsweise nicht als rational ausgedrückt werden kann Math.sin.


1
Das Mathn-Modul ist seit Ruby 2.2
Meier


6

Fixnum # to_r wird hier nicht erwähnt, es wurde seit Ruby 1.9 eingeführt. Es wandelt Fixnum in eine rationale Form um. Nachfolgend finden Sie Beispiele für seine Verwendung. Dies kann auch eine genaue Unterteilung ergeben, solange alle verwendeten Zahlen Fixnum sind.

 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

Beispiel, bei dem ein Float, der mit einer rationalen Zahl betrieben wird, das schwebende Ergebnis verdeckt.

a = 5.to_r   #=> (5/1) 
a = a * 5.0  #=> 25.0 
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.