# Is 2.0 Integer or Float?

I’d like to be able to do:

x = 2.0
assert x.integral?

the :integer method returns false in this case.
What would be a good way to write a different method to check?

On Nov 14, 2006, at 10:35 AM, S. Robert J. wrote:

I’d like to be able to do:

x = 2.0
assert x.integral?

the :integer method returns false in this case.
What would be a good way to write a different method to check?

2.0.is_a? Float
=> true

2.0.is_a? Integer
=> false

James Edward G. II

Hope the following helps:

irb(main):001:0> 2.0.class
=> Float
irb(main):002:0> 2.class
=> Fixnum
irb(main):003:0> 2.0.is_a?(Float)
=> true
irb(main):004:0> 2.0.is_a?(Fixnum)
=> false
irb(main):005:0> 2.is_a?(Float)
=> false
irb(main):006:0> 2.is_a?(Fixnum)
=> true

-Szymon

S. Robert J. wrote:

I’d like to be able to do:

x = 2.0
assert x.integral?

the :integer method returns false in this case.
What would be a good way to write a different method to check?

That depends on what you are trying to accomplish. Are you trying to
establish that the value is an integer expressed as a float?

#!/usr/bin/ruby -w

def integer_in_sheeps_clothing?(v)
return v.to_i == v
end

puts integer_in_sheeps_clothing?(5.0)

puts integer_in_sheeps_clothing?(5.0 + 1e-10)

Output:

true
false

On 11/14/06, S. Robert J. [email protected] wrote:

I’d like to be able to do:

x = 2.0
assert x.integral?

the :integer method returns false in this case.
What would be a good way to write a different method to check?

class Numeric
def is_integer?
Integer(self) == self
end
end

2.0.is_integer? #=> true
2.1.is_integer? #=> false
2.is_integer? #=> true

Blessings,
TwP

On 11/14/06, [email protected] [email protected] wrote:

asking if two values are within some delta (also represented as a
floating
point value) of each other.

Any numerical computation folks out there who can share their wisdom?

Maybe the value should be modeled as an integer with different units
of dollars to model monetary values.

IEEE floating point can store an exact representation of any integer
that the fp number is large enough to contain.
I’ve never used it this way, but supposedly that is used to handle
53-bit ints on platforms that have 64-bit floats and only 32-bit ints.

That may or may not be what the OP is trying to do.

On Nov 14, 2006, at 2:21 PM, Wilson B. wrote:

IEEE floating point can store an exact representation of any integer
that the fp number is large enough to contain.
I’ve never used it this way, but supposedly that is used to handle
53-bit ints on platforms that have 64-bit floats and only 32-bit ints.

That may or may not be what the OP is trying to do.

I’m pretty sure Lua uses floats for everything, for exactly this reason.

James Edward G. II

James Edward G. II wrote:

On Nov 14, 2006, at 2:21 PM, Wilson B. wrote:

IEEE floating point can store an exact representation of any integer
that the fp number is large enough to contain.
I’ve never used it this way, but supposedly that is used to handle
53-bit ints on platforms that have 64-bit floats and only 32-bit ints.

That may or may not be what the OP is trying to do.

I’m pretty sure Lua uses floats for everything, for exactly this reason.

How does that work? Is there an 11-bit pattern that signifies “use the
remaining 53 bits as a integer”? Do math library functions respect this?

On Nov 14, 2006, at 2:29 PM, Joel VanderWerf wrote:

reason.

How does that work? Is there an 11-bit pattern that signifies “use
the remaining 53 bits as a integer”? Do math library functions
respect this?

I have no idea how they do what they do:

http://lua-users.org/wiki/FloatingPoint

James Edward G. II

On Nov 14, 2006, at 11:35 AM, S. Robert J. wrote:

I’d like to be able to do:

x = 2.0
assert x.integral?

the :integer method returns false in this case.
What would be a good way to write a different method to check?

Maybe it is just me, I don’t have a lot of experience with floating
point
issues, but this request has a bad smell to it. Once you’ve decided to
model something with floating point values it seems a bit unusual to
want
to know if any particular value happens to be the exact floating point
representation of an integer. Isn’t the entire notion of equality
somewhat
ambiguous in the floating point world? I thought this is usually
handled by
asking if two values are within some delta (also represented as a
floating
point value) of each other.

Any numerical computation folks out there who can share their wisdom?

Maybe the value should be modeled as an integer with different units
of dollars to model monetary values.

Gary W.

Sander L. wrote:

On 11/14/06, Joel VanderWerf [email protected] wrote:

How does that work? Is there an 11-bit pattern that signifies “use the
remaining 53 bits as a integer”? Do math library functions respect this?

53 bits is just the mantissa size.
imagine using scientific notation a * 10^b with a<1 and 3 decimal
digits, this gives you accurate integers up to 1000.
999 => 0.999 * 10^3 exact
1001=> 0.100 * 10^4 overflowed

Ok, so they aren’t doing anything exceptional with the format. There’s
no special switching going on, just normal floating point math with
integer values.

On 11/14/06, Joel VanderWerf [email protected] wrote:

How does that work? Is there an 11-bit pattern that signifies “use the
remaining 53 bits as a integer”? Do math library functions respect this?

53 bits is just the mantissa size.
imagine using scientific notation a * 10^b with a<1 and 3 decimal
digits, this gives you accurate integers up to 1000.
999 => 0.999 * 10^3 exact
1001=> 0.100 * 10^4 overflowed

But depending upon how the “integer” was generated, it may still make
more sense to use an epsilon in the test (which certainly has the
“smell” that was mentioned earlier)

Integer(100.0 * 9.95) == 995 => false
(100.0 * 9.95) - 995.0 <= Float::EPSILON => true

# So you find yourself tempted to do this

class Float
def like_an_int
(self - self.round).abs <= Float::EPSILON
end
end

(100.0 * 9.95).like_an_int => false

On my system Float::EPSILON = 2.22044604925031e-016
(100.0 * 9.95) - 995.0 => -1.13686837721616e-013

Which is way bigger than EPSILON, it turns out you need to scale your
“EPSILON” by the relative magnitude of the numbers being compared.
This way leads to madness and general discomfort --> if you find
yourself in this neighborhood, switch to rational numbers (or scaled
integers), you will be happier.

pth

Bernard K. wrote:

/ …

the :integer method returns false in this case.
What would be a good way to write a different method to check?

x.class => Float 2.0 is a float not an integer

The OP is trying to establish whether the content of the float
variable is
an integer, not whether the variable has float type. That is relatively
easy to establish.

----- Original Message -----
From: “S. Robert J.” [email protected]
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” [email protected]
Sent: Tuesday, November 14, 2006 11:35 AM
Subject: Is 2.0 Integer or Float?

I’d like to be able to do:

x = 2.0
assert x.integral?

the :integer method returns false in this case.
What would be a good way to write a different method to check?

x.class => Float 2.0 is a float not an integer

Paul L. wrote:

Bernard K. wrote:

the :integer method returns false in this case.
What would be a good way to write a different method to check?

x.class => Float 2.0 is a float not an integer

The OP is trying to establish whether the content of the float
variable is
an integer, not whether the variable has float type. That is relatively
easy to establish.

Sorry to join this conversation late, but to me this is a strange
question. Floats are never integers. Integers are counting numbers with
exact values over a certain range determined by their internal
representation. While floating point numbers are approximations which
suffer from errors of precision. They may approach an integer bound and
yet never achieve it. So the question is what approximation is adequate
to say that a float is the integer that it approaches. What is close
enough?

Example:

irb(main):124:0> def is_integer(f)
irb(main):125:1> ((f.ceil - f).remainder(1).abs < 0.0000000001) or
((f.floor - f
).remainder(1).abs < 0.0000000001)
irb(main):126:1> end
=> nil
irb(main):127:0> n = 0.1
=> 0.1
irb(main):128:0> 100.times { puts “#{n} is a integer: #{is_integer(n)}”;
n += 0.
1 }
0.1 is a integer: false
0.2 is a integer: false
0.3 is a integer: false
0.4 is a integer: false
0.5 is a integer: false
0.6 is a integer: false
0.7 is a integer: false
0.8 is a integer: false
0.9 is a integer: false
1.0 is a integer: true
1.1 is a integer: false
1.2 is a integer: false
1.3 is a integer: false
1.4 is a integer: false
1.5 is a integer: false
1.6 is a integer: false
1.7 is a integer: false
1.8 is a integer: false
1.9 is a integer: false
2.0 is a integer: true
2.1 is a integer: false
2.2 is a integer: false
2.3 is a integer: false
2.4 is a integer: false
2.5 is a integer: false
2.6 is a integer: false
2.7 is a integer: false
2.8 is a integer: false
2.9 is a integer: false
3.0 is a integer: true
3.1 is a integer: false
3.2 is a integer: false
3.3 is a integer: false
3.4 is a integer: false
3.5 is a integer: false
3.6 is a integer: false
3.7 is a integer: false
3.8 is a integer: false
3.9 is a integer: false
4.0 is a integer: true
4.1 is a integer: false
4.2 is a integer: false
4.3 is a integer: false
4.4 is a integer: false
4.5 is a integer: false
4.6 is a integer: false
4.7 is a integer: false
4.8 is a integer: false
4.9 is a integer: false
5.0 is a integer: true
5.1 is a integer: false
5.2 is a integer: false
5.3 is a integer: false
5.4 is a integer: false
5.5 is a integer: false
5.6 is a integer: false
5.7 is a integer: false
5.8 is a integer: false
5.9 is a integer: false
5.99999999999999 is a integer: true
6.09999999999999 is a integer: false
6.19999999999999 is a integer: false
6.29999999999999 is a integer: false
6.39999999999999 is a integer: false
6.49999999999999 is a integer: false
6.59999999999999 is a integer: false
6.69999999999999 is a integer: false
6.79999999999999 is a integer: false
6.89999999999999 is a integer: false
6.99999999999999 is a integer: true
7.09999999999999 is a integer: false
7.19999999999999 is a integer: false
7.29999999999999 is a integer: false
7.39999999999999 is a integer: false
7.49999999999999 is a integer: false
7.59999999999999 is a integer: false
7.69999999999999 is a integer: false
7.79999999999999 is a integer: false
7.89999999999999 is a integer: false
7.99999999999999 is a integer: true
8.09999999999999 is a integer: false
8.19999999999999 is a integer: false
8.29999999999999 is a integer: false
8.39999999999999 is a integer: false
8.49999999999999 is a integer: false
8.59999999999999 is a integer: false
8.69999999999999 is a integer: false
8.79999999999998 is a integer: false
8.89999999999998 is a integer: false
8.99999999999998 is a integer: true
9.09999999999998 is a integer: false
9.19999999999998 is a integer: false
9.29999999999998 is a integer: false
9.39999999999998 is a integer: false
9.49999999999998 is a integer: false
9.59999999999998 is a integer: false
9.69999999999998 is a integer: false
9.79999999999998 is a integer: false
9.89999999999998 is a integer: false
9.99999999999998 is a integer: true

Dale M. wrote:

Paul L. wrote:

/ …

The OP is trying to establish whether the content of the float
variable is
an integer, not whether the variable has float type. That is relatively
easy to establish.

Sorry to join this conversation late, but to me this is a strange
question. Floats are never integers.

That depends on how we are defining our terms. In a mathematical sense,
of
course, yes. In a computer-science sense however, one can place an
integer
in a float variable, and it will behave itself as though it were an
integer
– for example, regardless of its value (within the allowed range), it
will
permit itself to be converted between bases without any of the
well-documented gotchas to which true floats are prone. Also, additions,
subtractions and multiplies will be carried out with the expected
integer
results.

Integers are counting numbers with
exact values over a certain range determined by their internal
representation.

And such an integer can be stored in a float variable type.

While floating point numbers are approximations which
suffer from errors of precision.

This refers to floats in float variables, not integers in float
variables.

They may approach an integer bound and
yet never achieve it. So the question is what approximation is adequate
to say that a float is the integer that it approaches. What is close
enough?

No, as a matter of fact, an integer stored in a float variable type
doesn’t
lose its identity as an integer. It is still an integer, and behaves
itself
in a way that a float cannot.

All your examples prove is that floats are not integers. But, hear me on
this, integers really are integers, no matter where they are located,
assuming they do not overflow the range of the variable in which they
are
stored.

#!/usr/bin/ruby -w

## 0.upto(1e6) do |i| fi = i.to_f puts “Error: #{i}” if(i != fi) end

The silence was deafening. I lost patience with more repetitions, but I
think I know the outcome.

You should know that many projects store integers in float variables in
cases where the float variable has more available bits of precision that
the platform’s integer data type. Those who do this know there is no
downside – the integer stored in the float variable won’t start
misbehaving itself just because of its new, upscale quarters.

Dale M. wrote:

Paul L. wrote:

Dale M. wrote:

Paul L. wrote:
You should know that many projects store integers in float variables in
cases where the float variable has more available bits of precision that
the platform’s integer data type. Those who do this know there is no
downside – the integer stored in the float variable won’t start
misbehaving itself just because of its new, upscale quarters.

I agree that storing integers in floats is possible as long as you only
use integer values for your computations and you do not exceed a
mantissa’s precision that everything will be wonderful.

If this is the world you wish to limit yourself to then:

def is_integer(f)
f.remainder(1) == 0
end

would be adequate as a test to determine is a value stored in a float is
an integer, but this will fail on many computed values that involve
non-integer values even if the expected result should be an integer
value.

I personally don’t see a valid application in Ruby since Fixnum and
Bignum handle precision well beyond that of Float.

Paul L. wrote:

Dale M. wrote:

Paul L. wrote:

All your examples prove is that floats are not integers. But, hear me on
this, integers really are integers, no matter where they are located,
assuming they do not overflow the range of the variable in which they
are
stored.

#!/usr/bin/ruby -w

## 0.upto(1e6) do |i| fi = i.to_f puts “Error: #{i}” if(i != fi) end

The silence was deafening. I lost patience with more repetitions, but I
think I know the outcome.

You should know that many projects store integers in float variables in
cases where the float variable has more available bits of precision that
the platform’s integer data type. Those who do this know there is no
downside – the integer stored in the float variable won’t start
misbehaving itself just because of its new, upscale quarters.

Yes, you can store integers in floats. This is usually done with the
exponent left at zero and the size of the mantissa limits the range of
valid integers. If the exponent must be used, it becomes a computed
value that is an approximation.

Using irb,

irb(main):163:0> 1e6.class => Float
irb(main):164:0> 1e22.to_i => 10000000000000000000000
irb(main):165:0> 1e23.to_i => 99999999999999991611392