Почему деление в Ruby возвращает целое число вместо десятичного значения?


256

Например:

9 / 5  #=> 1

но я ожидал 1.8. Как я могу получить правильный десятичный (нецелый) результат? Почему это возвращается1 вообще ?


4
Обратите внимание, что если вы на самом деле используете метод для возврата этого значения, вам не нужно присваивать его переменной; просто def method; a - b/8; endвернул бы результат вычисления из метода, поскольку последнее выражение в вызове метода является возвращаемым значением.
Phrogz

Ответы:


268

Это делает целочисленное деление. Вы можете сделать одно из чисел а Float, добавив .0:

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

10
Это работает, но ответ to_f ниже кажется более полезным. Является ли to_f более идиоматическим в Ruby?
notapatch

9
.to_fОтвет лучше , если вы разделив две переменные , которые содержат целые числа, например a.to_f / b. Если вы буквально делите два жестко запрограммированных целых числа (что, вероятно, странно), тогда использование 9.0 / 5подойдет.
Jefflunt

350

Это делает целочисленное деление. Вы можете использовать, to_fчтобы заставить вещи в режиме с плавающей запятой:

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

Это также работает, если ваши значения являются переменными, а не литералами. Преобразование одного значения в число с плавающей точкой является достаточным для приведения всего выражения к арифметике с плавающей запятой.


1
Это более «рельсовый» ответ, чем принятый ответ.
Шон Райан

@muistooshort: я не могу повторить это, извините. Я, вероятно, делал что-то не так.
Жоао Коста

4
@SeanRyan Почему именно Rails, а не Ruby в целом? Я не понимаю, почему (Ruby on) Rails-разработчик сделал бы эту конкретную вещь иначе, чем обычный Ruby-разработчик. Возможно, я просто придираюсь к семантике, и большинство людей просто считают (Ruby on) Rails и Ruby синонимичными в подобных случаях.
Чиното Вокро

169

Есть также Numeric#fdivметод, который вы можете использовать вместо:

9.fdiv(5)  #=> 1.8

1
Это самый быстрый метод, который я тестировал, единственный способ повысить производительность - разделить операнды, которые с самого начала являются плавающими. Я построил генератор простых чисел в Ruby для изучения синтаксиса, теперь я оптимизирую его, чтобы узнать, что работает лучше всего. Вот тест я соединял: требуют 'base64', требуют 'Zlib'; путы Zlib.inflate (Base64.decode64 ( "eJxlkMEOwiAQRO98hekFuGzxQEwPXvwR01ZqiYHqBk2Tln8XDlWgnDbM25nJonq9NaoD7ZTtR9PigxK09zM7AkgRHieXTYHOsBNf1nklM6B6TuhYpdp + rPgSdiCOi / d / kQ71QBOtAVFLEDly05 + UYQ2H + MckL6z0zioDdJG1S9K1K4iQAW66DhnmiqRYKEJFXMByux + XuOJ2XdO60dKsjC7aBtyTL5O5hLk ="))
Chinoto Vokro

Один вопрос, сохранит ли он точность, как мы используем «десятичную»?
Адам Айкен

39

Вы можете проверить это с помощью irb:

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

26

Вы можете включить mathnмодуль ruby .

require 'mathn'

Таким образом, вы сможете сделать деление в обычном режиме.

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

Таким образом, вы получаете точное деление (класс Rational), пока не решите применить операцию, которая, например, не может быть выражена как рациональная Math.sin.


1
Модуль mathn устарел начиная с ruby ​​2.2
Meier


6

Fixnum # to_r здесь не упоминается, он появился с версии 1.9. Он превращает Fixnum в рациональную форму. Ниже приведены примеры его использования. Это также может дать точное деление, если все используемые числа являются 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

Пример, в котором число с плавающей запятой, работающее с рациональным числом, покрывает результат с плавающей точкой.

a = 5.to_r   #=> (5/1) 
a = a * 5.0  #=> 25.0 
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.