Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why id function behaves differently with integer and float?

I tried the following code and It gave me different output.

>>> foo1 = 4
>>> foo2 = 2+2
>>> id(foo1)
37740064L
>>> id(foo2)
37740064L

>>> foo1 = 4.3
>>> foo2 = 1.3+3.0
>>> id(foo1)
37801304L
>>> id(foo2)
37801232L
>>>

I am using python 2.7.2. Why id function return different value in case of float but same value in case of integers?

like image 663
kvivek Avatar asked Apr 14 '13 08:04

kvivek


People also ask

Why the ID of float values are different when the same value is?

In that case the float value containing variable may contain same data but reason behind is to mathematical rules. The only two value are consider after the point & remaining are value get neglected. so the we get two different addresses of the same data containing variables.

Why does using float instead of int give me different results when all of my inputs are integers?

The reason you get different output is you perform a different computation: division behaves differently for integers and floating point numbers, except when the numerator is a multiple of the denominator.

How integers are different from floats?

Integers and floats are two different kinds of numerical data. An integer (more commonly called an int) is a number without a decimal point. A float is a floating-point number, which means it is a number that has a decimal place. Floats are used when more precision is needed.

How does Python distinguish between float and integer?

Numbers in Python exist in two chief forms: integers and floats. As noted in Lesson 02, integers are numbers without a decimal point, whereas floats are numbers with a decimal point. This is am important distinction that you MUST remember, especially when working with data imported from and exported to Excel.


3 Answers

That is because the result of id in numeric constants is implementation defined.

In your case, Python 2.7.2, IIRC, the issue is that the compiler builds a few useful integer constants as singletons, (from -1 to 100 or so). The rationale is that these numbers are used so frequently that it makes no sense to dynamically allocate them each time they are needed, they are simply reused.

But that constant singleton optimization is not useful for float values, other than maybe 0.0, there are too many of them! So each time a new float value is needed it is allocated, and it gets a different id.

For a more deeply insight, read the source! This file is from Python3, but the idea is the same: look for the small_ints array.

like image 127
rodrigo Avatar answered Sep 20 '22 00:09

rodrigo


id is never really predictable, not even for integers. With low the very integers 2 and 4, you just happen to hit the small integer cache. Try this:

>>> a = 12345
>>> b = 12345
>>> id(a)
33525888
>>> id(b)
33525852
>>>
like image 25
Michael Avatar answered Sep 20 '22 00:09

Michael


For small integers and strings, that are expected to be frequently used, Python uses internal memory optimization. Since any variable in Python is a reference to memory object, Python puts such small values into the memory only once. Then, whenever the same value is assigned to any other variable, it makes that variable point to the object already kept in memory. This works for strings and integers as they are immutable and if the variable value changes, effectively it's the reference used by this variable that is changed, the object in memory with original value is not itself affected.

That's why variables foo1 and foo2 in first case hold reference to the same integer object in memory with value 4 and therefore the ids are the same.

First of all, floating point numbers are not 'small', and, second, the same 4.3 in memory depending on calculations might be kept as 4.3123456789 and 4.31239874654 (just example numbers to explain). So these two values are two different objects, but during calculations and displaying the meaningful part looks the same, i.e. 4.3 (in fact there's obviously many more possible values in memory for the same meaningful floating point number). So reusing the same floating point number object in memory is problematic and doesn't worth it after all.

That's why in the second case foo1 and foo2 reference different floating point object in memory and therefore have different ids.

See more details on how floating point numbers are kept in memory:

http://floating-point-gui.de/

http://docs.python.org/2/tutorial/floatingpoint.html

Also, there's a big article on floating point numbers at Oracle docs.

@josliber, I edited the answer before reposting as you advised.

like image 45
Nikita Avatar answered Sep 21 '22 00:09

Nikita