Is there a way to simply check if a string value is a valid float value. Calling to_f on a string will convert it to 0.0 if it is not a numeric value. And using Float() raises an exception when it is passed an invalid float string which is closer to what I want, but I don't want to handle catching exceptions. What I really want is a method such as nan? which does exist in the Float class, but that doesn't help because a non-numeric string cannot be converted to a float without being changed to 0.0 (using to_f).
"a".to_f => 0.0 "a".to_f.nan? => false Float("a") => ArgumentError: invalid value for Float(): "a"
Is there a simple solution for this or do I need to write code to check if a string is a valid float value?
To check if a string is an integer or a float:Use the str. isdigit() method to check if every character in the string is a digit. If the method returns True , the string is an integer. If the method returns False , the string is a floating-point number.
To check if a string is a valid Float, use the Float. parseFloat() method, with the string to be checked passed as a parameter.
Check if the value has a type of number and is not an integer. Check if the value is not NaN . If a value is a number, is not NaN and is not an integer, then it's a float.
Here's one way:
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
If you want to avoid the monkey-patch of String, you could always make this a class method of some module you control, of course:
module MyUtils def self.valid_float?(str) !!Float(str) rescue false end end MyUtils.valid_float?("a") #false
An interesting fact about the Ruby world is the existence of the Rubinius project, which implements Ruby and its standard library mostly in pure Ruby. As a result, they have a pure Ruby implementation of Kernel#Float, which looks like:
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
This provides you with a regular expression that matches the internal work Ruby does when it runs Float(), but without the exception. So you could now do:
class String def nan? self !~ /^\s*[+-]?((\d+_?)*\d+(\.(\d+_?)*\d+)?|\.(\d+_?)*\d+)(\s*|([eE][+-]?(\d+_?)*\d+)\s*)$/ end end
The nice thing about this solution is that since Rubinius runs, and passes RubySpec, you know this regex handles the edge-cases that Ruby itself handles, and you can call to_f on the String without any fear!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With