假设我有以下代码:
x = 0.8 y = 1.0
检查y是否等价于Integer的最佳方法是什么?目前我正在做的是:
y
Integer
y.to_int == y
这很有效但我觉得应该有更好的办法。
bgibtngc1#
用1对该值进行mod,然后检查该值是否等于0。
mod
if y % 1 == 0
xkftehaa2#
一般来说,当你不关心数值类型时,你应该使用==来比较数字,这应该是大多数时候。当你真正关心类型时,你应该使用从Numeric #eql?继承的对象相等比较。
==
你可以只问一个数字对象它是否是一个整数。例如,Numeric #integer?让你问一个数字检查它自己并返回一个布尔值:
[1, 1.2, 1.02e+1].map(&:integer?) #=> [true, false, false]
如果你关心的只是 * y * 是否是整数,那么这就是你要做的。
y = 1 y.integer? #=> true y = 1.0 y.integer? #=> false
如果你想做一些更复杂的事情,比如在相等比较中避免自动的Numeric类型转换,唯一真正的限制是你的想象力和你想在代码中清晰表达的想法。Numeric、Float、Integer、Object、String和其他类中有很多方法可以让你执行类型转换和严格的相等比较。下面是一些例子。
使用各种方法转换为Integer,然后严格检查对象是否相等:
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)
如果要创建一个布尔表达式,而不使用==进行的自动数字转换,则可以使用从Numeric #zero?继承的类特定方法。例如:
(y % 1).zero? y.modulo(1).zero?
如果对某些类型的数字,模运算无法完成,那么可以使用Float #ceil或Float #floor:
y = 1.2 (y - y.floor).zero? #=> false y = 1.02e+1 (y.floor - y).zero? #=> false
7lrncoxx3#
你可能根本不想这么做。浮点运算容易产生舍入误差,你认为得到6.0的一系列运算实际上可能得到5.9999999999999。在这种情况下,任何检查值是否为整数的操作都将失败。即使你可能希望它成功。通常比较浮点数和给定精度内的整数版本是更好的方法,比如if (x - x.to_i).abs < 0.001。
if (x - x.to_i).abs < 0.001
wfveoks04#
虽然有各种各样的方法可以做到这一点,但有一种方法在其他答案中没有提到,但对我来说似乎是直观的:
y == y.truncate
您也可以将“monkey-patch“作为一个方法:
class Numeric def is_int? self == self.truncate end end
之后您可以拨打:
y.is_int?
1.对于monkey-patch选项,请注意不要将y.is_int?与y.integer?混淆,因为y.integer?是不同的(后者对于1是正确的,但对于1.0不是,而前者对于两者都是正确的)。1.在某些情况下,数字的内部浮点表示可能会导致错误的结果(例如,(10*(0.2+0.1)).is_int?(在monkey-patch之后)返回false,因为10*(0.2+0.1)给出3.0000000000000004)。不管是好是坏,我认为这类问题的完整解决方案超出了本答案的范围,因为我不相信它会突然出现在你表达问题的特定方式中。对于任何人来说,这确实很重要,存在对这个问题的更详细的分析,例如here,应该在适当的时候参考。1.您还可以选择不同的名称来代替is_int?--也许integer_equivalent?会更好?
y.integer?
1
1.0
(10*(0.2+0.1)).is_int?
false
10*(0.2+0.1)
3.0000000000000004
is_int?
integer_equivalent?
4条答案
按热度按时间bgibtngc1#
用1对该值进行
mod
,然后检查该值是否等于0。xkftehaa2#
靶区; DR
一般来说,当你不关心数值类型时,你应该使用
==
来比较数字,这应该是大多数时候。当你真正关心类型时,你应该使用从Numeric #eql?继承的对象相等比较。最简单的事情可能工作
你可以只问一个数字对象它是否是一个整数。例如,Numeric #integer?让你问一个数字检查它自己并返回一个布尔值:
如果你关心的只是 * y * 是否是整数,那么这就是你要做的。
其他解决方案
如果你想做一些更复杂的事情,比如在相等比较中避免自动的Numeric类型转换,唯一真正的限制是你的想象力和你想在代码中清晰表达的想法。Numeric、Float、Integer、Object、String和其他类中有很多方法可以让你执行类型转换和严格的相等比较。下面是一些例子。
使用#eql?
使用各种方法转换为Integer,然后严格检查对象是否相等:
是否检查带有#zero的余数?
如果要创建一个布尔表达式,而不使用
==
进行的自动数字转换,则可以使用从Numeric #zero?继承的类特定方法。例如:将#ceil或#floor用于减法
如果对某些类型的数字,模运算无法完成,那么可以使用Float #ceil或Float #floor:
7lrncoxx3#
你可能根本不想这么做。浮点运算容易产生舍入误差,你认为得到6.0的一系列运算实际上可能得到5.9999999999999。在这种情况下,任何检查值是否为整数的操作都将失败。即使你可能希望它成功。通常比较浮点数和给定精度内的整数版本是更好的方法,比如
if (x - x.to_i).abs < 0.001
。wfveoks04#
虽然有各种各样的方法可以做到这一点,但有一种方法在其他答案中没有提到,但对我来说似乎是直观的:
简单的解决方案
Monkey-patch添加:
您也可以将“monkey-patch“作为一个方法:
之后您可以拨打:
备注:
1.对于monkey-patch选项,请注意不要将
y.is_int?
与y.integer?
混淆,因为y.integer?
是不同的(后者对于1
是正确的,但对于1.0
不是,而前者对于两者都是正确的)。1.在某些情况下,数字的内部浮点表示可能会导致错误的结果(例如,
(10*(0.2+0.1)).is_int?
(在monkey-patch之后)返回false
,因为10*(0.2+0.1)
给出3.0000000000000004
)。不管是好是坏,我认为这类问题的完整解决方案超出了本答案的范围,因为我不相信它会突然出现在你表达问题的特定方式中。对于任何人来说,这确实很重要,存在对这个问题的更详细的分析,例如here,应该在适当的时候参考。1.您还可以选择不同的名称来代替
is_int?
--也许integer_equivalent?
会更好?