【问题标题】:Checking if a Float is equivalent to an integer value in Ruby检查浮点数是否等价于 Ruby 中的整数值
【发布时间】:2014-09-25 03:33:37
【问题描述】:

假设我有以下代码:

x = 0.8
y = 1.0

检查y 是否等同于Integer 的最佳方法是什么?目前我正在做:

y.to_int == y

这行得通,但我觉得应该有更好的方法。

【问题讨论】:

    标签: ruby type-conversion


    【解决方案1】:

    mod的值是1,检查值是否等于0。

    if y % 1 == 0
    

    【讨论】:

      【解决方案2】:

      TL;DR

      一般来说,当你不关心数字类型时,你应该使用==来比较数字,这应该是大多数时候。当你真正关心类型时,你应该使用继承自 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、Float、Integer、Object、String 和其他类中有许多方法可以让您执行类型转换和严格的相等比较。下面举几个例子。

      使用#eql?

      使用各种方法转换为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)
      

      用#zero 检查余数?

      如果您想创建一个布尔表达式,而不需要 == 进行的自动数字转换,您可以使用从 Numeric#zero? 继承的特定于类的方法。例如:

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

      将#ceil 或#floor 与减法结合使用

      如果模数对某些类型的数字不起作用,那么您可以使用Float#ceilFloat#floor

      y = 1.2
      (y - y.floor).zero?
      #=> false
      
      y = 1.02e+1
      (y.floor - y).zero?
      #=> false
      

      【讨论】:

      • 整数?方法不直观,因为 3.0.integer? == 错误。
      【解决方案3】:

      您可能甚至不想这样做。浮点运算会受到舍入误差的影响,并且您会认为会给出一系列操作,例如6.0 实际上可能会给出 5.9999999999999 。在这种情况下,任何检查该值是否为整数都会失败,即使您可能希望它成功。 通常,将浮点数与给定精度内的整数版本进行比较是一种更好的方法,例如if (x - x.to_i).abs < 0.001

      【讨论】:

      • 在这种情况下,我知道它是准确的 - 我正在检查数字是否是 0.25 的精确倍数(例如 (x * 4) % 1 == 0)。
      猜你喜欢
      • 1970-01-01
      • 2013-11-29
      • 1970-01-01
      • 2011-08-13
      • 2022-01-13
      • 2023-03-14
      • 2014-12-13
      相关资源
      最近更新 更多