Shubham
Shubham

Reputation: 22317

Unexpected value of floor() function in python

import numpy
import math

x = numpy.roots([2,-2,(21 - 21**2)])
print x[0], math.floor(x[0])

The output is:

15.0 14.0 

and I expect

15.0 15.0

I don't expect any reason to have the floor equal to 14.0. Please explain!

Upvotes: 1

Views: 523

Answers (4)

jterrace
jterrace

Reputation: 67073

I've used a function called fAlmostEqual before, based on numpy's allclose function:

import math

def fAlmostEqual(a, b, rtol=1.0000000000000001e-05, atol=1e-08):
    """Checks if the given floats are almost equal. Uses the algorithm
    from numpy.allclose."""
    return math.fabs(a - b) <= (atol + rtol * math.fabs(b))

Creating a fuzzy floor function based on this:

def fuzzyFloor(v):
    """Returns the floor of the given number, unless it is equal to its
    ceiling (within floating point error)."""
    floor = math.floor(v)
    if fAlmostEqual(floor+1, v):
        return floor+1
    return floor

print fuzzyFloor(14.9999999999999)
print fuzzyFloor(15)
print fuzzyFloor(14.99)
print fuzzyFloor(14.5)

This prints:

15.0
15.0
14.0
14.0

Upvotes: 2

Steven Rumbalski
Steven Rumbalski

Reputation: 45542

Your code does not give the same thing for me:

>>> import numpy
>>> import math
>>>
>>> x = numpy.roots([2,-2,(21 - 21**2)])
>>> print x[0], math.floor(x[0])
15.0 15.0

However, there is a number 14 lurking here. It's one of the roots:

>>> print x
[ 15. -14.]

Upvotes: 0

Sven Marnach
Sven Marnach

Reputation: 601739

Floating-point numbers are only approximations of some value, and all computations might introduce rounding errors. Printing a floating point-number might also round the number to fewer digits. Try

print repr(x[0]), repr(math.floor(x[0]))

to make sure all digits are shown. I guess it will show something like 14.9999999999999.

Upvotes: 2

David Heffernan
David Heffernan

Reputation: 612993

It would seem that x[0] is ever so slightly less than 15 and so floor takes the value down to 14. The root finding algorithm is numerical rather than symbolic and floating point arithmetic is not exact.

Upvotes: 2

Related Questions