If I do something like
a = Math::log(-1)
then a properly takes the value NaN.
Is there any way to explicitly assign the variable “a” to NaN
(or Inifinity or -Infinity) to begin with? I tried finding
“NaN” as a constant but couldn’t locate it. It doesn’t appear
to be a constant in Float or Math.
I don’t understand what you mean by ‘assign the variable “a”
to NaN’.
NaNs and infinite values are best tested for using the nan? and
infinite? methods. Note that infinite? returns +1 or -1 for
positive and negative infinities and nil for finite numbers:
> In the C library that I am trying to expose to Ruby there is a
> constant for a NULL rectangle. You would get a NULL
> rectangle, for example, if you asked for the intersection of
> two disjoint rectangles. The NULL rectangle is very different
> from the "zero rectangle" (a rectangle whose corner is at the
> origin and whose height and width are zero).
> The NULL rectangle is implemented as a rectangle whose lower
> left corner is at (+Infinity, +Infinity) and whose height and
> width are both zero.
> I wanted to make sure that if I exposed that constant to Ruby
> that it would behave as expected. As a result, I was trying
> to experiment with "irb" and I wanted to create an instance of
> my "Point" object whose x and y coordinates were +Infinity. I
> was looking to do something like:
> apoint = CGPoint.new(Float::Infinity, Float::Infinity)
> when I couldn't find Infinity I started looking for NaN as
> well. I found some sample code on the internet that showed
> how to generate a NaN result, but not how to initialize a
> float to NaN or +/-Infinity.
> It seems, in some cases, it might be valuable to assign a
> float to "a value that is not a legal value" similar to the
> way one might assign a pointer to NULL in C, or even a object
> reference to nil in Ruby. But that may be just me :-)
I wanted the same thing for a simple statistics class that used Kalman
filter-style updates instead of the more traditional (and prone to
numerical problems) sum of x, sum of x^2 based calculations. Like
you, I wanted to distinguish between the case where I had no data and
the case where I had zero for mean, variance, min, or max. I did the
following:
class SimpleStats
attr_reader :n, :mean, :variance, :min, :max
def initialize
reset
end
def reset
@n = 0
@variance = @mean = Math::log(-1)
@min = 1.0 / 0.0
@max = -@min
end
def newObs(x)
@max = x if x > @max
@min = x if x < @min
@n += 1
if (@n > 1)
x -= @mean
@mean += x / @n
@variance = (@n - 2.0) / (@n - 1.0) * @variance + x * x / @n
else
@mean = x
@variance = 0.0
end
end
def stdDeviation
Math::sqrt @variance
end
end
Note that by initializing min and max to +/- Infinity, respectively,
the update stage for them doesn’t need a special case for the first
time. If only the same were true of the mean and variance updates…
If anyone has any suggestions for tightening this up, by the way,
they’d be appreciated!
–paul