I'm using the following function in Python 2.7.3 and Kivy 1.8.0 to fade-in a Grid widget:
def __init__(self, **kwargs):
# ...Init parent class here...
self.grid.opacity = 0.0
Clock.schedule_interval(self.show, 1 / 10)
def show(self, value):
if self.grid.opacity == 1.0:
return False
else:
self.grid.opacity += 0.1
show() is executed infinitely, self.grid.opacity == 1.0 always returs False, so the scheduler never removes the function.
I thought, and the documentation says, that opacity is a NumericProperty which defaults to 1.0, but I'm changing its value right before show() is called.
This is what I've tried:
if self.grid.opacity == NumericProperty(1.0):
if float(self.grid.opacity) == 1.0:
It doesn't work. Also, I'm sure self.grid.opacity is 1.0 and type() retrieves float right before I make the comparison.
This works:
if str(self.grid.opacity) == "1.0":
But obviously I don't like this solution.
Any ideas?
It is probably not Python specific. Read What Every Programmer Should Know About Floating-Point Arithmetic.
0.1 is not exactly representable as a IEEE754 double-precision floating point. So I guess that the floating point (parsed from) 0.1 (which is not exactly one tenth) is not converted as a string "0.1"
Might be a float comparison issue. I don't know the application, but float's are never exact, so testing them for equality can cause problems. You can try something like:
if abs(float(self.grid.opacity) - 1.0) < .001:
pass
An example of funny float behavior, at least on my setup:
>>> .1 + .1 + .1 == .3
False
>>> .1 + .1 == .2
True
This is your problem:
>>> q=0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1
>>> str(q)
'1.0'
>>> q
0.9999999999999999
>>> q==1
False
Bottom line never compare floats with ==, period.
As others have stated, the problem is due to the way floating point numbers are stored. While you could try to use workarounds, there's a better way to do this: Animation.
In __init__:
self.grid.opacity = 0
anim = Animation(opacity=1)
anim.start(self.grid)
#Basile Starynkevitch answers why this is happening, the nature of floating point numbers is at work here. The general form for doing this kind of comparison is:
abs(numberA - numberB) <= SOMEEPSILON
where SOMEEPSILON is a number you deem to be an acceptable margin.
If you're working with smaller numbers and not worried about a rounding error you can sys.float_info.epsilon
So as I commented by combining the two you get:
abs(self.grid.opacity- 1.0) <= sys.float_info.epsilon
The definition of epsilon's value in the docs is:
difference between 1 and the least value greater than 1 that is representable as a float
Which is a another way of saying, the smallest value between 1 and the number right before it.
So for example, if python could only represent numbers up to 2 decimal places, epsilon would be the difference between 1.00 and 0.99 (in reality the value is much smaller than that)
Related
Could someone help me to understand the following statement?
Why this is True:
3.0 == 3
but this one not?
4 ** 0.5 != 2
(4**0.5 = 2.0, and according to above statement 2.0 is equal to 2), but I get False. WHy?
The != operator does the opposite of ==.
(In your first example, you wrote = but I think you mean ==.)
With !=, it evaluates True if the two numbers are not equal to each other, otherwise it is False. (Here, "equal" can include an integer and a floating point number having the same numerical value.)
So here:
>>> 4 ** 0.5 != 2
False
>>> 4 ** 0.5 == 2
True
Unlike some languages, Python does not care about floats and ints when it comes to comparing. It will treat 4 and 4.0 as the exact same when comparing them to other numbers. You can debate the reliability of this feature of Python, but for the purposes of answering this question this is relevant.
Now we know this, we can see that 4 * .5 is the same is 2.0 which is the same as 2. The actual reason the second argument is false has nothing to do with the number being a float or not, but actually to do with the operator you are using.
== will return true if both sides of the equation ARE equal, whereas != will return true if both sides of the equation ARE NOT equal.
The second statement is using the != operator and so is returning false because both sides are equal. If both sides where not equal, it would return false.
Hope this cleared things up!
I'm looking to differentiate between a number like
2.0 or 2 and an actual fractional number such as 2.4. What would be the best way to do this? Currently I'm doing:
def is_fractional(num):
if not str(num).replace('.','').isdigit(): return
return float(num) != int(num)
>>> is_fractional(2)
False
>>> is_fractional(2.1)
True
>>> is_fractional(2.0)
False
>>> is_fractional('a')
>>>
That operation is built-in:
>>> 5.0.is_integer()
True
>>> 5.00000001.is_integer()
False
>>> 4.9999999.is_integer()
False
Documentation is here.
ADDENDUM
The initial solution only works for float. Here's a more complete answer, with tests:
from decimal import Decimal
def is_integer(x):
if isinstance(x, int):
return True
elif isinstance(x, float):
return x.is_integer()
elif isinstance(x, Decimal):
return x.as_integer_ratio()[1] == 1
return False
good = [
0,
0.0,
3,
-9999999999999999999999,
-2.0000000000000,
Decimal("3.000000"),
Decimal("-9")
]
bad = [
-9.99999999999999,
"dogs",
Decimal("-4.00000000000000000000000000000000001"),
Decimal("0.99999999999999999999999999999999999")
]
for x in good:
assert is_integer(x)
for x in bad:
assert not is_integer(x)
print("All tests passed")
If some of your numbers are decimal.Decimals, they might have range issues where conversion to float fails, or drops the fractional part that actually exists, depending on their precision:
>>> import decimal
>>> x = decimal.Decimal('1.00000000000000000000000000000000000001')
>>> str(x)
'1.00000000000000000000000000000000000001'
>>> float(x).is_integer()
True
>>> y = decimal.Decimal('1e5000')
>>> str(y)
'1E+5000'
>>> float(y)
inf
The str method will generally work (modulo problem cases like the one illustrated above), so you could stick with that, but it might be better to attempt to use is_integer and use a fallback if that fails:
try:
return x.is_integer()
except AttributeError:
pass
(as others note, you'll need to check for int and long here as well, if those are allowed types, since they are integers by definition but lack an is_integer attribute).
At this point, it's worth considering all of the other answers, but here's a specific decimal.Decimal handler:
# optional: special case decimal.Decimal here
try:
as_tuple = x.as_tuple()
trailing0s = len(list(itertools.takewhile(lambda i: i == 0, reversed(as_tuple[1]))))
return as_tuple[2] + trailing0s < 0
except (AttributeError, IndexError): # no as_tuple, or not 3 elements long, etc
pass
Why do not check if the difference between the truncation to integer and the exact value is not zero?
is_frac = lambda x: int(x)-x != 0
Python includes a fractions module that generates fractions (rational numbers) from strings, floats, integers, and much more. Just create a Fraction and check whether its denominator is other than 1 (the Fraction constructor will automatically reduce the number to lowest terms):
from fractions import Fraction
def is_fractional(num):
return Fraction(num).denominator != 1
Note that the method above may raise an exception if the conversion to a Fraction fails. In this case, it's not known whether the object is fractional.
If you are dealing with decimal module or with a float object, you can do this easily:
def is_factional(num):
return isinstance(num, (float, Decimal))
Here is one way to do it (assuming e.g. 2/2 is not "fractional" in the sense you have in mind):
# could also extend to other numeric types numpy.float32
from decimal import Decimal
def is_frac(n):
numeric_types = (int, float, Decimal)
assert isinstance(n, numeric_types), 'n must be numeric :/'
# (ints are never fractions)
if type(n) is int: return False
return n != float(int(n))
# various sorts of numbers
ns = [-1, -1.0, 0, 0.1, 1, 1.0, 1., 2.3, 1e0, 1e3, 1.1e3,
Decimal(3), Decimal(3.0), Decimal(3.1)]
# confirm that values are as expected
dict(zip(ns, [is_frac(n) for n in ns]))
This will only work if n is an int or a float or decimal.Decimal. But you could extend it to handle other numeric types such as numpy.float64 or numpy.int32 by just including them in numeric_types.
I am dealing with the following problem with unittest2:
assertAlmostEqual(69.88, 69.875, places=2) # returns True
but
assertAlmostEqual(1.28, 1.275, places=2) # returns False
I think problem is in the assertAlmostEqual method:
def assertAlmostEqual(self, first, second, places=None, ...):
if first == second:
# shortcut
return
...
if delta is not None:
...
else:
if places is None:
places = 7
if round(abs(second-first), places) == 0:
return
...
raise self.failureException(msg)
Should it instead be:
if abs(round(second, places) - round(first, places)) == 0
return
Your proposed fix doesn't make any difference, as you can easily demonstrate:
>>> places = 2
>>> first, second = 69.88, 69.875
>>> round(abs(second-first), places)
0.0
>>> abs(round(second, places) - round(first, places))
0.0
This is a problem with floating point precision, see e.g. Is floating point math broken? 69.88 cannot be represented exactly:
>>> "{:.40f}".format(69.88)
'69.8799999999999954525264911353588104248047'
The difference in the second example is
0.005
And even without mentioned biases of floating points result of round will be 0.01, so these numbers really different with 2-places precision
This method compares difference between numbers. It is kinda standard of comparing float numbers actually
So the problem is not with implementation, but with you expectations, that is different from common float comparison
>>> 100**0.5 != 4+6
False
>>> 100**0.5 == 4+6
True
>>> 4+6
10
>>> 100**0.5
10.0
>>> 10.0==10
True
Who can tell me why 10.0==10 is True?
I think 10.0 is a float and 10 is int,I know in java they are not equal.
Quoting from http://docs.python.org/2/library/stdtypes.html#numeric-types-int-float-long-complex
Python fully supports mixed arithmetic: when a binary arithmetic
operator has operands of different numeric types, the operand with the
“narrower” type is widened to that of the other, where plain integer
is narrower than long integer is narrower than floating point is
narrower than complex.
So, 10 is widened to 10.0. Thats why 10 == 10.0
Because that's the way Python defines equality for floats and integers. If the float represents a whole number, it's equal to the integer representing the same number (and even has the same hash code). Note that Java does something to similar effect (even though == cannot be overloaded by classes in Java). 10.0 == 10 is true because == with mixed (numeric) arguments performs binary numeric promotion which turns the int 10 into the floating point number 10.0.
u can use
>>> 10 == 10.0
True
>>> 10 is 10.0
False
is is the identity comparison.
== is the equality comparison.
is means is same instance. It evaluates to true if the variables on either side of the operator point to the same object and false otherwise.
Python automatically type converts during comparisons if possible and sensible to do so.
>>> False == 0
True
>>> True == 1
True
>>> True == 0
False
>>> True == 22
False
Also illustrates this behaviour.
This question already has answers here:
Is False == 0 and True == 1 an implementation detail or is it guaranteed by the language?
(3 answers)
Closed 9 years ago.
Anyways when debuging my code I found statement that basically subtracted boolean from float.
Then I tried following in python console:
>>> 15.0 - True
14.0
>>> 15.0 - False
15.0
Can anyone explain to me:
Why subtracting booleans from numeric types is legal (the docs only state that you can do and, not and or on boolean values: http://docs.python.org/3/library/stdtypes.html#boolean-operations-and-or-not)
Has this any practical use?
It is legal, because bool is a subclass of int:
>>> bool.__bases__
(<type 'int'>,)
>>> True == 1
True
>>> False == 0
True
Yes, it has some practical application. For example it was possible to do something like that before ternary statement was introduced:
result = [value_if_false, value_if_true][condition]
Which basically does what would be done in this code:
if condition:
result = value_if_false
else:
result = value_if_true
Other practical usages are:
you can sum several checks / booleans to receive number of results equaling True,
you can multiply by the result of the check:
result = can_count_a * a + can_count_b * b
http://docs.python.org/3/library/stdtypes.html#boolean-values
Boolean values are the two constant objects False and True. They are used to represent truth values (although other values can also be considered false or true).
In numeric contexts (for example when used as the argument to an arithmetic operator), they behave like the integers 0 and 1, respectively.
not really nowadays, but you can write
result = numeric_value * a_bool (this one is used a lot, for example, in shader languages)
instead of
result = numeric_value if a_bool else 0
or
result = (value_if_false, value_if_true)[a_bool]
Don't do any of that though.
It's mostly what people with experience in lower-level languages expect, why take that away from them? In C, true and false are still macros for 1 and 0.
Before 2.3, there was no bool type in Python as well, so when it was introduced making it a subclass of int made sure no code was broken.
True evaluates to 1 and False evaluates to 0.
>>> True is 1
False
>>> True == 1
True
>>>
Bool is a subclass of int. As stated in PEP-285:
6) Should bool inherit from int?
=> Yes.
In an ideal world, bool might be better implemented as a separate
integer type that knows how to perform mixed-mode arithmetic.
However, inheriting bool from int eases the implementation enormously
(in part since all C code that calls PyInt_Check() will continue to
work -- this returns true for subclasses of int). Also, I believe
this is right in terms of substitutability: code that requires an int
can be fed a bool and it will behave the same as 0 or 1. Code that
requires a bool may not work when it is given an int; for example, 3 &
4 is 0, but both 3 and 4 are true when considered as truth values.
This isn't of any much practical use and there are other answers with sudo examples of using bools. I thought it would be good to have some real examples:
f,b="Fizz","Buzz"
print "\n".join([["",f,b,f+b][(x%3==0) + 2*(x%5==0)] or str(x) for x in range(1,101)])
The section in question:
["",f,b,f+b][(x%3==0) + 2*(x%5==0)]
The selection of the return each line is based on two boolean expressions, if both are true we get (True) + 2*(True) which evaluates to 4 which is a fizzbuzz. Not too hard to understand once you get used to the idea that True == 1 and False == 0
Further more keeping with the theme:
print '\n'.join(['Fizz'*(not i%3) + 'Buzz'*(not i%5) or str(i) for i in range(1, 101)])
This example relies on what happens when you multiply strings in python:
>>> "Noelkd" * False
''
And that not True evaluates to 0:
>>> not True == 0
True
Uses for this fall into two categories:
Making harder to read code.
Competing in code golf competitions.