How to Express Infinity in Ruby

How to express infinity in Ruby?

If you use ruby 1.9.2, you can use:

>> Float::INFINITY #=> Infinity
>> 3 < Float::INFINITY #=> true

Or you can create your own constant using the following*:

I've checked that in Ruby 1.8.6, 1.8.7, and 1.9.2 you have Float.infinite?.

PositiveInfinity = +1.0/0.0 
=> Infinity

NegativeInfinity = -1.0/0.0
=> -Infinity

CompleteInfinity = NegativeInfinity..PositiveInfinity
=> -Infinity..Infinity

*I've verified this in Ruby 1.8.6 and 1.9.2

RoR: Is there a value for infinite?

Asked and answered here: How to express infinity in Ruby?

but the short of it is:

Float::INFINITY

Is there a way to express 'infinite time'?

It's possible using DateTime::Infinity class:

future = DateTime.now..DateTime::Infinity.new
future.include?(1_000_000.years.from_now) #=> true

Why is Float::INFINITY == Float::INFINITY in Ruby?

In more technical terms, it all comes down to the IEEE 754 standard for floating-point arithmetics.

The IEEE 754 standard does implicitly define Infinity == Infinity to
be true. The relevant part of the standard is section 5.7: "Four
mutually exclusive relations are possible [between two IEEE 754
values]: less than, equal, greater than, and unordered. The last case
arises when at least one operand is NaN."

Between any pair of floating point values exactly one of these four
relations is true. Therefore, since Infinity is not NaN, Infinity is
not unordered with respect to itself. Having one of (Infinity <
Infinity) and (Infinity > Infinity) be true wouldn't be consistent, so
(Infinity == Infinity).

This was taken from http://compilers.iecc.com/comparch/article/98-07-134

How to express Infinity in C in a ruby extension

I found the answer in this question.

rb_const_set(rb_mKernel, rb_intern("Infinity"), rb_float_new(INFINITY));

There are no compiler warnings for this.

For loop... Forever

You can use Numeric#step without passing a limit:

0.step(by: 2) { |i| puts i }

Output:

0
2
4
6
...

You can also build your own Enumerator:

step2 = Enumerator.new do |y|
a = 0
loop do
y << a
a += 2
end
end

step2.each { |i| puts i }

Geometric mean in Ruby returning Infinity for large arrays

Your value is overflowing what a Float can hold. Instead consider using BigDecimal:

require 'bigdecimal'

def gmean(x)
prod = BigDecimal.new 1
x.each { |v| prod *= BigDecimal.new(v) }
prod ** (1.0 / x.size)
end

gmean(sample_array2).to_f #=> 4711.148446895203

Note that your method can be simplified to a more functional style:

def gmean(xs)
one = BigDecimal.new 1
xs.map { |x| BigDecimal.new x }.inject(one, :*) ** (one / xs.size)
end

Problems with infinite time range in Rails

You cannot store Infinity as part of a time range in Rails. I believe this is because Infinity is going to be inserted as a string value and interpreted as a float when pulled out of the native PSQL oid. So, any date range from Date -> Float will not be viable. But you can manage to create your own range with pseudo (1 million years from now) dates or you can just use two separate date fields and interpret them appropriately in the model. Begin date, end date.

In Rails 4.2+, you can store a Float::INFINITY value inside your datetime type. Example.

User.first.update(begin_date: DateTime.now, end_date: 'infinity')
User.first.end_date # => Infinity

However, end_date will not be a valid date. You're just storing the string in the database and you're pulling out a float when your call it.

Here's the actual (Rails 4.2) code that handles that:

module ActiveRecord
module ConnectionAdapters
module PostgreSQL
module OID # :nodoc:
class DateTime < Type::DateTime # :nodoc:
include Infinity

def type_cast_for_database(value)
if has_precision? && value.acts_like?(:time) && value.year <= 0
bce_year = format("%04d", -value.year + 1)
super.sub(/^-?\d+/, bce_year) + " BC"
else
super
end
end

def cast_value(value)
if value.is_a?(::String)
case value
when 'infinity' then ::Float::INFINITY
when '-infinity' then -::Float::INFINITY
when / BC$/
astronomical_year = format("%04d", -value[/^\d+/].to_i + 1)
super(value.sub(/ BC$/, "").sub(/^\d+/, astronomical_year))
else
super
end
else
value
end
end
end
end
end
end
end

Again, you will not be able to do date time comparisons with a float. But, it's probably simple enough to have a special case for these two values -::Float::INFINITY and ::Float::INFINITY

Can someone explain to me NaN in Ruby?

IEEE 754 floating point numbers define -INFINITY +INFINITY and NotANumber to make it possible to react to lets say division by zero. you can also calculate with these for eg 2 + INF = INF

NaN isn't a uniqe ruby feature, they are numeric in java, c++, ... too



Related Topics



Leave a reply



Submit