Dlaczego podział w Rubim zwraca liczbę całkowitą zamiast wartości dziesiętnej?


256

Na przykład:

9 / 5  #=> 1

ale się spodziewałem 1.8. Jak uzyskać poprawny wynik dziesiętny (nie całkowity)? Dlaczego w ogóle wraca 1?


4
Zauważ, że jeśli faktycznie używasz metody do zwrócenia tej wartości, nie musisz przypisywać jej do zmiennej; po prostu def method; a - b/8; endzwróci wynik obliczenia z metody, ponieważ ostatnim wyrażeniem w wywołaniu metody jest wartość zwracana.
Phrogz

Odpowiedzi:


268

Robi podział na liczby całkowite. Możesz zrobić jedną z liczb a Float, dodając .0:

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

10
Działa to, ale poniższa odpowiedź to_f wydaje się bardziej przydatna. Czy to jest bardziej idiomatyczne w Ruby?
notapatch

9
.to_fOdpowiedź brzmi lepiej jeśli dzieląc dwie zmienne, które zawierają liczby całkowite, np a.to_f / b. Jeśli dosłownie dzielisz dwie zakodowane liczby całkowite (co jest prawdopodobnie dziwne), użycie 9.0 / 5jest w porządku.
jefflunt

350

Robi podział na liczby całkowite. Możesz użyć, to_faby wymusić przejście w tryb zmiennoprzecinkowy:

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

Działa to również, jeśli twoje wartości są zmiennymi zamiast literałów. Konwersja jednej wartości na liczbę zmiennoprzecinkową jest wystarczająca, aby przekonać całe wyrażenie do arytmetyki zmiennoprzecinkowej.


1
Jest to odpowiedź bardziej „szynowa” niż odpowiedź zaakceptowana.
Sean Ryan,

@muistooshort: Przepraszam, nie mogę tego zreplikować. Prawdopodobnie robiłem coś złego.
Joao Costa

4
@SeanRyan Dlaczego konkretnie Railsy zamiast Ruby w ogóle? Nie rozumiem, dlaczego programista (Ruby on) Rails zrobiłby tę konkretną rzecz inaczej niż zwykły programista Ruby. Być może po prostu poprawiam semantykę i większość ludzi widzi (Ruby on) Rails i Ruby jako synonim w takich przypadkach.
Chinoto Vokro

169

Istnieje również Numeric#fdivmetoda, której możesz użyć zamiast tego:

9.fdiv(5)  #=> 1.8

1
Jest to najszybsza metoda, którą przetestowałem, jedynym sposobem na zwiększenie wydajności jest podzielenie operandów, które na początku są zmiennoprzecinkowe. Zbudowałem generator liczb pierwszych w Rubim, aby nauczyć się składni, teraz optymalizuję ją, aby dowiedzieć się, co działa najlepiej. Oto benchmark ułożyła: require 'base64'; wymagają 'zlib'; puts Zlib.inflate (Base64.decode64 ( "eJxlkMEOwiAQRO98hekFuGzxQEwPXvwR01ZqiYHqBk2Tln8XDlWgnDbM25nJonq9NaoD7ZTtR9PigxK09zM7AkgRHieXTYHOsBNf1nklM6B6TuhYpdp + rPgSdiCOi / d / kQ71QBOtAVFLEDly05 + UYQ2H + MckL6z0zioDdJG1S9K1K4iQAW66DhnmiqRYKEJFXMByux + XuOJ2XdO60dKsjC7aBtyTL5O5hLk ="))
Chinoto Vokro

Jedno pytanie, czy zachowałoby precyzję, tak jakbyśmy używali „dziesiętnego”?
Adam Aiken,

39

Możesz to sprawdzić za pomocą irb:

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

26

Możesz dołączyć mathnmoduł ruby .

require 'mathn'

W ten sposób będziesz mógł normalnie dokonać podziału.

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

W ten sposób otrzymujesz dokładny podział (klasa wymierna), dopóki nie zdecydujesz się zastosować operacji, która nie może być wyrażona na przykład jako wymierna Math.sin.


1
Moduł matematyczny jest przestarzały od wersji Rubin 2.2
Meier


6

Fixnum # to_r nie jest tutaj wymienione, zostało wprowadzone od wersji Ruby 1.9. Przekształca Fixnum w racjonalną formę. Poniżej znajdują się przykłady jego zastosowań. Może to również dać dokładny podział, o ile wszystkie użyte liczby to 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

Przykład, w którym liczba zmiennoprzecinkowa działająca na liczbie wymiernej obejmuje wynik do liczby zmiennoprzecinkowej.

a = 5.to_r   #=> (5/1) 
a = a * 5.0  #=> 25.0 
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.