Проверка, эквивалентен ли Float целочисленному значению в Ruby - PullRequest
28 голосов
/ 22 февраля 2011

Скажите, у меня есть следующий код:

x = 0.8
y = 1.0

Какой лучший способ проверить, что y эквивалентно Integer? На данный момент я делаю:

y.to_int == y

, который работает, но я чувствую, что должен быть лучший способ.

Ответы [ 3 ]

66 голосов
/ 22 февраля 2011

Вы mod значение с 1, и проверьте, равно ли значение 0.

if y % 1 == 0
3 голосов
/ 24 сентября 2014

TL; DR

Как правило, вы должны использовать == для сравнения чисел, когда вас не интересует числовой тип, который должен быть в большинстве случаев. Когда вы действительно заботитесь о типе, вы должны использовать сравнение на равенство объектов, унаследованное от Numeric # eql? .

Самое простое, что могло бы сработать

Вы можете просто спросить числовой объект, является ли он целым числом. Например, Числовое # целое число? позволяет попросить число проверить себя и вернуть логическое значение:

[1, 1.2, 1.02e+1].map(&:integer?)
#=> [true, false, false]

Если все, что вас волнует, это выяснить, является ли y целым числом, то это путь. Используя ваши собственные примеры:

y = 1
y.integer?
#=> true

y = 1.0
y.integer?
#=> false

Другие решения

Если вы пытаетесь сделать что-то более сложное, например, пытаетесь избежать автоматического преобразования числовых типов в сравнениях на равенство, единственным реальным ограничением является ваше воображение и идея, которую вы пытаетесь четко выразить в своем коде. В Numeric, Float, Integer, Object, String и других классах есть много методов, которые позволили бы вам вести разговоры типов и проводить строгие сравнения на равенство. Вот несколько примеров.

Использовать #eql?

Используйте различные методы для преобразования в целое число, а затем проверяйте со строгим равенством объектов:

y = 1.2

# All of these will return false.
y.eql? y.truncate
y.eql? y.floor
y.eql? y.to_i
y.eql? Integer(y)

Проверить остатки с помощью #zero?

Если вы хотите создать логическое выражение без автоматических числовых преобразований, сделанных с помощью ==, вы можете использовать специфичный для класса метод, унаследованный от Numeric # zero? . Например:

(y % 1).zero?
y.modulo(1).zero?

Используйте #ceil или #floor с вычитанием

Если по определенным типам чисел по модулю не получается, вы можете использовать Float # ceil или Float # floor :

y = 1.2
(y - y.floor).zero?
#=> false

y = 1.02e+1
(y.floor - y).zero?
#=> false
3 голосов
/ 22 февраля 2011

Вы, вероятно, даже не хотите этого делать. Арифметика с плавающей точкой подвержена ошибкам округления, и ряд операций, которые вы думаете, дает, например, 6.0 на самом деле может дать 5.9999999999999. В этом случае любая проверка того, что значение является целым числом, завершится неудачей, даже если вы, вероятно, предполагали, что оно будет успешным. Обычно лучше сравнить число с плавающей запятой с целочисленной версией с заданной точностью, например if (x - x.to_i).abs < 0.001.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...