ruby on rails how to deal with NaN
NaN
is instance of Float
. Use Float#nan?
method.
>> nan = 0.0/0 # OR nan = Float::NAN
=> NaN
>> nan.class
=> Float
>> nan.nan?
=> true
>> nan.is_a?(Float) && nan.nan?
=> true
>> (nan.is_a?(Float) && nan.nan?) ? 0 : nan
=> 0
UPDATE
NaN
could also be an instance of BigDecimal
:
((nan.is_a?(Float) || nan.is_a?(BigDecimal)) && nan.nan?) ? 0 : nan
or
{Float::NAN => 0, BigDecimal::NAN => 0}.fetch(nan, nan)
how to make NaN value as the lowest when ordering Active Record objects?
apparently it is just the way postgresql ordering with NaN
the workaround for this is using SQL
syntax to change the NaN
into null
then set an options to set the null
value to be the last when ordering
DownloadSpeed.order(Arel.sql("nullif(avg, 'NaN') desc nulls last"))
related questions :
Postgres order column with NaN values
Why do NULL values come first when ordering DESC in a PostgreSQL query?
Check if number is NaN
Quickest way is to use this:
under_the_test.to_f.nan? # gives you true/false e.g.:
123.to_f.nan? # => false
(123/0.0).to_f.nan? #=> true
Also note that only Floats have #nan?
method defined on them, that's the reason why I'm using #to_f
in order to convert result to float first.
Tip: if you have integer calculation that potentially can divide by zero this will not work:
(123/0).to_f.nan?
Because both 123 and 0 are integers and that will throw ZeroDivisionError
, in order to overcome that issue Float::NAN
constant can be useful - for example like this:
return Float::NAN if divisor == 0
return x / divisor
How do I screen out NaNs when comparing floats in Ruby?
You can produce an array of NaN
values in the console like so:
[ 0.0 / 0.0 ] * 3
# => [NaN, NaN, NaN]
It's not entirely clear what your code is doing, but it might be worth noting that it's the max
which is throwing the exception, and not the equality test. Incidentally, if you are trying to compare each array value against the maximum value - you might want to max
outside of the map
, to avoid having to evaluate it multiple times.
Building on top the other answer here on rejecting NaN
s, you can put it all together to get something like:
# set up dummy data - 2 values and 3 NaNs
guesses_arr = [ 0.0 / 0.0 ] * 3 + [ 2.0, 3.0 ]
puts "guesses arr: #{guesses_arr}"
# => [NaN, NaN, NaN, 2.0, 3.0]
# remove NaNs in place
guesses_arr.reject!(&:nan?)
maximum = guesses_arr.max
guesses_arr.map!{|str| str.is_a?(Numeric) && str == maximum ? str : 0}
# => [ 0, 3.0 ]
Edit: if you have integers mixed up in the array, try converting them into floats first:
# set up dummy data - including floats and integers
guesses_arr = [ 0.0 / 0.0 ] * 3 + [ 2.0, 3.0, 0 ]
guesses_arr.map!(&:to_f).reject!(&:nan?)
# => [ 2.0, 3.0, 0.0 ]
How do I check if a var is NaN in ruby?
despite the fact I set "i" to "NaN", I'm getting the baffling output above.
This is the correct behaviour, in accordance with the IEEĘ754 specification. You'll find the same thing in any other language, assuming it has implemented the specification correctly.
# In Ruby:
Float::NAN == Float::NAN
#=> false
// In JavaScript:
NaN == NaN
// false
The specification also provides a list of recommended functions, which includes:
isnan(x)
- a predicate for"x is a NaN"
, equivalent to"x ≠ x"
.
In ruby, this has been implemented as Float#nan?
:
Float::NAN.nan?
#=> true
Under the hood, this is indeed asserting that x != x
:
int
isnan(double n)
{
return double_ne(n, n);
}
static int
double_ne(double n1, double n2)
{
return n1 != n2;
}
Ruby division infinity/NaN should return 0
Very similar to: How can I redefine Fixnum's + (plus) method in Ruby and keep original + functionality?
class Float
alias_method :old_div, :/
def /(y)
return NAN if self == y && y == 0.0
return INFINITY if self == 1.0 && y == 0.0
self.old_div(y)
end
end
I know the code above might not be what you exactly want. Feel free to customize it the way you want =)
How to check if an array contains Float::NAN
To check, you can use:
[1, 2, 3, 'a', 'b', Float::NAN].any?{|item| item.respond_to?(:nan?) && item.nan?}
(or try
, if you use Rails)
And as for why, take a look at What is the rationale for all comparisons returning false for IEEE754 NaN values?
Related Topics
Rails - Multi Tenant Application with Customization Framework
Can't Setup Ruby Environment - Installing Fii Gem Error
Webmock Simulate Failing API (No Internet, Timeout ++)
Ruby 'Gets' That Works Over Multiple Lines
How to Define a Method in Ruby Using Splat and an Optional Hash at the Same Time
"Dyld: Library Not Loaded", "Libruby.1.9.1.Dylib" When Calling "Mvim ." in the Command Line
Ruby: Overriding the Puts Method
How Would I Go About Converting This Time String to Epoch Time in Ruby
Actioncable Connected Users List
Respond_With Redirect with Notice Flash Message Not Working
How to Use H2 as Embedded Database in Postgres-Compat Mode, from Jruby/Rails
Start and Call Ruby Http Server in the Same Script
+= Operator Appears to Modify Frozen String
Using Form_For Tag with Get Method
Yaml::Load Raises Undefined Class/Module Error
What Are the Meanings of the Hash Keys When Calling Objectspace.Count_Objects
What Regex How to Use to Get the Domain Name from a Url in Ruby