Is 2.0 Integer or Float?

S

S. Robert James

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?
 
J

James Edward Gray II

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?
=> false

James Edward Gray II
 
S

Szymon Rozga

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
 
T

Tim Pease

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
 
G

gwtmp01

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
instead of floating point? For example using units of pennies instead
of dollars to model monetary values.

Gary Wright
 
W

Wilson Bilkovich

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
instead of floating point? For example using units of pennies instead
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.
 
J

James Edward Gray II

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 Gray II
 
J

Joel VanderWerf

James said:
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?
 
S

Sander Land

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
 
J

Joel VanderWerf

Sander said:
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.
 
P

Patrick Hurley

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
 
B

Bernard Kenik

----- Original Message -----
From: "S. Robert James" <[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
 
D

Dale Martenson

Paul said:
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
 
D

Dale Martenson

Paul said:
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
 
D

Dale Martenson

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top