With scientific notation, two different floats evaluate as equal - python

How come the following expression evaluates to true?
In [0]: 1e18 == (1e18 + 50)
Out[0]: True
When replacing the scientific notation by exponentiation, this evaluates, as one would expected, to False:
In [1]: 10**18 == (10**18 + 50)
Out[1]: False

You do not have two pairs of floats. The top example, being scientific notation, is a pair of floats. Since the added difference is less than float precision, they compare as equal.
The bottom example is a pair of integers. You can easily check this with the type function. Python's long integers have no problem keeping the needed 18 digits of accuracy.
>>> type(1e18)
<class 'float'>
>>> type(10**18)
<class 'int'>

Related

How does Python compare 'int' to 'float' objects?

The documentation about numeric types states that:
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 integer is narrower than floating point, which is narrower than complex. Comparisons between numbers of mixed type use the same rule.
This is supported by the following behavior:
>>> int.__eq__(1, 1.0)
NotImplemented
>>> float.__eq__(1.0, 1)
True
However for large integer numbers something else seems to happen since they won't compare equal unless explicitly converted to float:
>>> n = 3**64
>>> float(n) == n
False
>>> float(n) == float(n)
True
On the other hand, for powers of 2, this doesn't seem to be a problem:
>>> n = 2**512
>>> float(n) == n
True
Since the documentation implies that int is "widened" (I assume converted / cast?) to float I'd expect float(n) == n and float(n) == float(n) to be similar but the above example with n = 3**64 suggests differently. So what rules does Python use to compare int to float (or mixed numeric types in general)?
Tested with CPython 3.7.3 from Anaconda and PyPy 7.3.0 (Python 3.6.9).
The language specification on value comparisons contains the following paragraph:
Numbers of built-in numeric types (Numeric Types — int, float, complex) and of the standard library types fractions.Fraction and decimal.Decimal can be compared within and across their types, with the restriction that complex numbers do not support order comparison. Within the limits of the types involved, they compare mathematically (algorithmically) correct without loss of precision.
This means when two numeric types are compared, the actual (mathematical) numbers that are represented by these objects are compared. For example the numeral 16677181699666569.0 (which is 3**34) represents the number 16677181699666569 and even though in "float-space" there is no difference between this number and 16677181699666568.0 (3**34 - 1) they do represent different numbers. Due to limited floating point precision, on a 64-bit architecture, the value float(3**34) will be stored as 16677181699666568 and hence it represents a different number than the integer numeral 16677181699666569. For that reason we have float(3**34) != 3**34 which performs a comparison without loss of precision.
This property is important in order to guarantee transitivity of the equivalence relation of numeric types. If int to float comparison would give similar results as if the int object would be converted to a float object then the transitive relation would be invalidated:
>>> class Float(float):
... def __eq__(self, other):
... return super().__eq__(float(other))
...
>>> a = 3**34 - 1
>>> b = Float(3**34)
>>> c = 3**34
>>> a == b
True
>>> b == c
True
>>> a == c # transitivity demands that this holds true
False
The float.__eq__ implementation on the other hand, which considers the represented mathematical numbers, doesn't infringe that requirement:
>>> a = 3**34 - 1
>>> b = float(3**34)
>>> c = 3**34
>>> a == b
True
>>> b == c
False
>>> a == c
False
As a result of missing transitivity the order of the following list won't be changed by sorting (since all consecutive numbers appear to be equal):
>>> class Float(float):
... def __lt__(self, other):
... return super().__lt__(float(other))
... def __eq__(self, other):
... return super().__eq__(float(other))
...
>>> numbers = [3**34, Float(3**34), 3**34 - 1]
>>> sorted(numbers) == numbers
True
Using float on the other hand, the order is reversed:
>>> numbers = [3**34, float(3**34), 3**34 - 1]
>>> sorted(numbers) == numbers[::-1]
True

how to get result based on float or int in python

I'm trying to determine result based on the weather the output is int or float.
it just prints same number twice. Whether my input odd or even number.
number = int(input())
mod = number/2
if type(mod) == int():
print(mod)
else:
print(number)
Your type comparison is wrong. Calling a type results in creating an instance of the type with a default value. int() resolves to zero(0) and comparing a type to zero is always false. Remove the parentheses to test for the type correctly.
>>> type(0) == int
True
>>> type(0.0) == float
True
However, the type of the result is fixed in this instance, and the type depends on the version of Python you are running. The result of the division operator(/) changes.
In Python 3, division always returns float, so type(mod) in your example would always be <type 'float'>.
In Python 2, 3/2 (integer divided by integer) gives an int result (rounded toward negative infinity, e.g. 3/2==1 and -3/2==-2), so type(mod) in your example would always be <type 'int'>. Python 2 can be made to work like Python 3 with from __future__ import division.
In both versions, you can force integer division with //.
Examples
Python 2.7
>>> type(2/2)
<type 'int'>
>>> type(3/2)
<type 'int'>
>>> from __future__ import division
>>> type(2/2)
<type 'float'>
>>> type(3/2)
<type 'float'>
>>> type(2//2)
<type 'int'>
>>> type(3//2)
<type 'int'>
Python 3.8
>>> type(2/2)
<class 'float'>
>>> type(3/2)
<class 'float'>
>>> type(2//2)
<class 'int'>
>>> type(3//2)
<class 'int'>
The Fix
If you want to test for whole numbers, use the modulus operator (%) to compute a remainder. Both int and float zero values are considered false:
>>> if 3 % 2:
... print('odd')
...
odd
There's a difference between int and int():
int is the type
int() is calling the type to construct an int; it will always return 0
So your trying to compare a type with 0, which doesn't make sense.
For type checking, use isinstance. Example: isinstance(3, int)
isinstance()
Try isinstance() to compare data types in python. Your Modified Code :
number = int(input())
mod = number/2
print(type(mod))
if isinstance(mod, int):
print(mod)
else:
print(number)
Do Have a Look.
In programming language generally we use typecast concept.First you need to understand the difference between the datatype and functions i.e int and int()
Number Type Conversion
Python converts numbers internally in an expression containing mixed types to a common type for evaluation. But sometimes, you need to coerce a number explicitly from one type to another to satisfy the requirements of an operator or function parameter.
Type int(x) to convert x to a plain integer.
Type long(x) to convert x to a long integer.
Type float(x) to convert x to a floating-point number.
Type complex(x) to convert x to a complex number with real part x and imaginary part zero.
Type complex(x, y) to convert x and y to a complex number with real part x and imaginary part y. x and y are numeric expressions

Python code percentage number compare problem

when i compared tow percentage number it gives me wrong answer
a="{0:%}".format(85/100)
b="{0:%}".format(9/100)
if b>a :
print("done")
it should be pass if condition while its give me done in answer
when i compare two percentage numbers it gives me wrong answer
No, the interpreter gives the correct answer.
The variables get these string values:
a = '85.000000%'
b = '9.000000%'
You are complaining about this string comparison result:
>>> '9' > '85'
True
Or more simply, since they differ in the 1st character, about this result:
>>> '9' > '8'
True
If you would prefer a numeric comparison,
then strip the percent and recover the numbers:
>>> float(b[:-1]) > float(a[:-1])
False

python unittest2 assertAlmostEqual with `places` works incorrectly

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

Python why 100**0.5 == 4+6 is true?

>>> 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.

Categories

Resources