确定字符串是否为有效的浮点值

Ben*_*n5e 30 ruby ruby-on-rails

有没有办法简单地检查字符串值是否是有效的浮点值.如果字符串不是数值,则在字符串上调用to_f会将其转换为0.0.使用Float()会在传递一个更接近我想要的无效浮点字符串时引发异常,但我不想处理捕获异常.我真正想要的是像nan这样的方法吗?它存在于Float类中,但这没有用,因为非数字字符串无法转换为float而不会更改为0.0(使用to_f).

"a".to_f => 0.0

"a".to_f.nan? => false

Float("a") => ArgumentError: invalid value for Float(): "a"
Run Code Online (Sandbox Code Playgroud)

有没有一个简单的解决方案或我是否需要编写代码来检查字符串是否是有效的浮点值?

Gre*_*ell 36

这是一种方式:

class String
  def valid_float?
    # The double negation turns this into an actual boolean true - if you're 
    # okay with "truthy" values (like 0.0), you can remove it.
    !!Float(self) rescue false
  end
end

"a".valid_float? #false
"2.4".valid_float? #true
Run Code Online (Sandbox Code Playgroud)

如果你想避免使用String的猴子补丁,你总是可以将它作为你控制的某个模块的类方法,当然:

module MyUtils
  def self.valid_float?(str)
    !!Float(str) rescue false
  end
end
MyUtils.valid_float?("a") #false
Run Code Online (Sandbox Code Playgroud)


Yeh*_*atz 28

关于Ruby世界的一个有趣的事实是Rubinius项目的存在,它实现了Ruby及其标准库,主要是纯Ruby.因此,他们有一个纯粹的Ruby实现Kernel#Float,它看起来像:

def Float(obj)
  raise TypeError, "can't convert nil into Float" if obj.nil?

  if obj.is_a?(String)
    if obj !~ /^\s*[+-]?((\d+_?)*\d+(\.(\d+_?)*\d+)?|\.(\d+_?)*\d+)(\s*|([eE][+-]?(\d+_?)*\d+)\s*)$/
      raise ArgumentError, "invalid value for Float(): #{obj.inspect}"
    end
  end

  Type.coerce_to(obj, Float, :to_f)
end
Run Code Online (Sandbox Code Playgroud)

这为您提供了一个正则表达式,它与Ruby运行Float()时所做的内部工作相匹配,但没有例外.所以你现在可以这样做:

class String
  def nan?
    self !~ /^\s*[+-]?((\d+_?)*\d+(\.(\d+_?)*\d+)?|\.(\d+_?)*\d+)(\s*|([eE][+-]?(\d+_?)*\d+)\s*)$/
  end
end
Run Code Online (Sandbox Code Playgroud)

关于这个解决方案的好处是,由于Rubinius运行并传递RubySpec,你知道这个正则表达式处理Ruby本身处理的边缘情况,你可以毫不畏惧地调用String上的to_f!


Ben*_*and 8

# Edge Cases:
# numeric?"Infinity" => true is_numeric?"Infinity" => false


def numeric?(object)
true if Float(object) rescue false
end

#Possibly faster alternative
def is_numeric?(i)
i.to_i.to_s == i || i.to_f.to_s == i
end
Run Code Online (Sandbox Code Playgroud)

  • 注意“更快的选择”将为“5.00”返回 false (2认同)

Mar*_*n13 6

红宝石 2.6+

Ruby 2.6 添加了一个新的exception关键字参数Float.

所以,现在检查一个字符串是否包含一个有效的浮点数很简单:

Float('22.241234', exception: false)
# => 22.241234

Float('abcd', exception: false)
# => nil
Run Code Online (Sandbox Code Playgroud)

这是文档的链接

  • 这应该是 Ruby 2.6 之后的首选答案。https://www.rubydoc.info/stdlib/core/Kernel:Float (3认同)