Memory representation doesn't really have anything to do with it (or at least, it doesn't prevent certain integers from comparing equal to equivalent real numbers).
2 == 2. is implemented by int.__eq__(2, 2.), which is defined to handle integer/float comparisons by making appropriate type conversions. Since int is a "narrower" type than float, 2 is first converted to a floating point value. (As an implementation detail, I suspect this is done by int.__eq__ calling float.__eq__(2., 2) and the conversion is done there, rather than the int type knowing any particular details about how floating-point values are represented.)
Note that not every int can be represent exactly as a floating-point value, as int uses arbitrary precision but float is fixed. For example, on my machine
>>> 2000000000000000000000000000000000 == 2000000000000000000000000000000000.
False
(I copy-pasted the integer to produce the floating-point literal, so the 0s line up.)