Is 2.0 Integer or Float?

Discussion in 'Ruby' started by S. Robert James, Nov 14, 2006.

  1. 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?
    S. Robert James, Nov 14, 2006
    #1
    1. Advertising

  2. On Nov 14, 2006, at 10:35 AM, S. Robert James 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 Gray II
    James Edward Gray II, Nov 14, 2006
    #2
    1. Advertising

  3. S. Robert James

    Szymon Rozga Guest

    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

    On Nov 14, 11:34 am, "S. Robert James" <> 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?
    Szymon Rozga, Nov 14, 2006
    #3
  4. S. Robert James

    Tim Pease Guest

    On 11/14/06, S. Robert James <> 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
    Tim Pease, Nov 14, 2006
    #4
  5. S. Robert James

    Guest

    On Nov 14, 2006, at 11:35 AM, S. Robert James 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
    instead of floating point? For example using units of pennies instead
    of dollars to model monetary values.

    Gary Wright
    , Nov 14, 2006
    #5
  6. On 11/14/06, <> wrote:
    >
    > On Nov 14, 2006, at 11:35 AM, S. Robert James 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
    > 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.
    Wilson Bilkovich, Nov 14, 2006
    #6
  7. On Nov 14, 2006, at 2:21 PM, Wilson Bilkovich 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 Gray II
    James Edward Gray II, Nov 14, 2006
    #7
  8. James Edward Gray II wrote:
    > On Nov 14, 2006, at 2:21 PM, Wilson Bilkovich 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?

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
    Joel VanderWerf, Nov 14, 2006
    #8
  9. On Nov 14, 2006, at 2:29 PM, Joel VanderWerf wrote:

    > James Edward Gray II wrote:
    >> On Nov 14, 2006, at 2:21 PM, Wilson Bilkovich 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?


    I have no idea how they do what they do:

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

    James Edward Gray II
    James Edward Gray II, Nov 14, 2006
    #9
  10. S. Robert James

    Sander Land Guest

    On 11/14/06, Joel VanderWerf <> 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
    Sander Land, Nov 14, 2006
    #10
  11. Sander Land wrote:
    > On 11/14/06, Joel VanderWerf <> 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.

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
    Joel VanderWerf, Nov 14, 2006
    #11
  12. 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
    Patrick Hurley, Nov 14, 2006
    #12
  13. ----- Original Message -----
    From: "S. Robert James" <>
    Newsgroups: comp.lang.ruby
    To: "ruby-talk ML" <>
    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
    Bernard Kenik, Nov 15, 2006
    #13
  14. Paul Lutus wrote:
    > Bernard Kenik 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

    --
    Posted via http://www.ruby-forum.com/.
    Dale Martenson, Nov 16, 2006
    #14
  15. Paul Lutus wrote:
    > Dale Martenson wrote:
    >
    >> Paul Lutus 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


    --
    Posted via http://www.ruby-forum.com/.
    Dale Martenson, Nov 17, 2006
    #15
  16. Dale Martenson wrote:
    > Paul Lutus wrote:
    >> Dale Martenson wrote:
    >>
    >>> Paul Lutus 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.

    --
    Posted via http://www.ruby-forum.com/.
    Dale Martenson, Nov 17, 2006
    #16
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Andy
    Replies:
    7
    Views:
    6,225
    Roedy Green
    May 10, 2004
  2. Jim West
    Replies:
    4
    Views:
    1,392
    Jeff Schwab
    Jan 16, 2004
  3. Jukka Lehtonen

    operator== (float, float)

    Jukka Lehtonen, Aug 4, 2004, in forum: C++
    Replies:
    5
    Views:
    2,401
    Jukka Lehtonen
    Aug 5, 2004
  4. bd
    Replies:
    0
    Views:
    595
  5. Carsten Fuchs
    Replies:
    45
    Views:
    1,485
    James Kanze
    Oct 8, 2009
Loading...

Share This Page