Python int unexpected result - python

Can someone explain me why x and y give completely different results?
>>> x=int(5) * 1e50
>>> x
5e+50
>>> y=int(5e50)
>>> y
499999999999999996610474337180813988230854220972032
The python manual says that integer can be of arbitrary length regardless the available memory, x and y as I known are integers but the result is completely different but are equivalent expressions, is 5e50 interpreted as float before int conversion? If so, why?

int(5) is an int, 1e50 is a float. If you multiply them, the int(5) will be converted to the larger type (which is a float) and then multiplied with 1e50. The result is of type float, not int.
int(5e50) converts the float to an int and is therefore printed as an integer of, as you say, arbitrary length.

Related

pandas astype applied to long integer returns a truncated result

wondering if someone came across this issue before
I'm trying to cast a float column in a dataframe to integer , and i'm getting strange results, this is my code :
proj_id['test2'] = proj_id['campaign_id'].astype('int64')
proj_id[proj_id['campaign_id']==23847591030830034][['campaign_id','test2']]
so my campaign_id which was
23847591030830034
becomes 23847591030830032
i have tried to suppress scientific expression, rounding, ... but it seems like the conversion truncates a byte off my integer
thank you for your help
This seems like it is a matter of representation.
When you do indexing you are casting 23847591030830034 to float which then gets compared with another float that is more accurately represented as 23847591030830032.0 but it is a difference so small that it gets rounded to the same float:
>>> floated = float(23847591030830034)
>>> inted = 23847591030830032
>>> floated == float(inted)
True
So it seems that the float representation for both integers is the same hence the discrepancy.

Why does x // y floor division with floats not return an integer in Python 3?

I am dividing 2 floats (or ints as well) with double slash like
t = x // y
In this case t must be an integer number, but python returns it as float.
>>> x, y = 3.0, 2.0
>>> x // y
1.0
By the convention and documentation, the output type of x // y is float if at least one of x or y is float. My question is WHY is the convention that way: What is the advantage of getting the result in float, and not int?
For my understanding, floor division always returns an integer. So the relation int(x//y) == x//y always holds. While there are some corner cases such as nan, "integer floor division" also has corner cases such as division by zero.
So my question is why float is better? In what cases will it differ?
This is not a duplicate of this question which asks if this is a bug. Instead, I want to know what is the reason why this behaviour is advantageous.
TLDR: Forcing // to be (float, float) -> int would not have any benefit, but unnecessary cost and type loss whenever -> float is sufficient.
In general, computation of // when any operand is a float is only correct if performed as float: a float operand may contain a fractional part that cannot be represented as an integer.
>>> 4.3 // 1.1
3.0
>>> int(4.3) // int(1.1)
4
As such, // for any float operand is inherently a float computation and yields such a result (CPython purely uses C double arithmetic). Providing the result as int would still compute the result as float and merely convert it to int – there would be no gain in precision.
With the behaviour specified by PEP 238, programmers can decide for themselves whether they desire to enforce int type or prefer the real float result.

Python binary float to integer conversion using ctypes

Please help me to understand this code snippet:
def binary_float_to_int(float_number: float) -> int:
return ctypes.c_uint.from_buffer(ctypes.c_float(float_number)).value
The results from these inputs:
print(binary_float_to_int(7.1746481e-43))
print(binary_float_to_int(5.3809861e-43))
Are: 512 & 384
Why does the simple Python conversion int(7.1746481e-43) not work?
Are there any other ways to do this type of conversion?
The ctypes code is:
Put the floating point number in a 32-bit C (IEEE 754-format) ctypes.c_float(float_number)
Treat that same 4-byte value, as an C unsigned int. ctypes.c_uint.from_buffer()
Extract that unsigned integer value .value
Your numbers are correct, if you want the raw 32-bit value of those floating point numbers expressed as integers. Here's another way to do it:
>>> import struct
>>> struct.unpack('i',struct.pack('f',7.1746481e-43))[0]
512
>>> struct.unpack('i',struct.pack('f',5.3809861e-43))[0]
384
These generate the 4-byte float32 value, then unpack it as an integer.
7.1746481e-43 is a very small value close to zero. int() returns the integer portion...in this case, zero, so that's as expected as well.

Python: How to differentiate whether input is an integer, or floating point

I'm a beginner trying to learn Python and decided to try an exercise where I would take an input, and distinguish its type; whether its an integer, floating point or a string.
As I understand it, Python treats all inputs as strings, so even when I enter a number/decimal point, the input is considered a string. I have overcome the first step in differentiating whether the input is a string or otherwise via this:
def get():
prompt = 'Give a number or a word.\n'
x = input(prompt)
try:
float(x)
print('You entered a number.')
except:
print('You entered a string.')
I take advantage of 'try' and 'except', as float(x) will return an error if x is a string and not a number/floating point. Next, I deduce that I can use a similar method to distinguish between integers and floating point numbers, but I don't know what can cause an error for an integer that wouldn't for a floating point, vice versa. (since float(x) where x is an integer works fine)
Is there such a thing so that I can use a similar method to distinguish between decimal number inputs and integers?
There are two questions within your question.
To handle the string > int/float, you could take advantage of ast.literal_eval first:
>>> import ast
>>> print(type(ast.literal_eval("2"))
int
>>> print(type(ast.literal_eval("3.4"))
float
>>> print(ast.literal_eval("3e2"))
300.0
To check for type, you're looking for isinstance I think.
>>> x = 2
>>> print(isinstance(x, int))
True
>>> y = 3.4
>>> print(isinstance(y, int))
False
>>> print(isinstance(y, float))
True
So, putting these two together you could use an if statement like that:
if isinstance(ast.literal_eval(x), int):
# do whatever you want if it's an int
elif isinstance(ast.literal_eval(x), float):
# do whatever you want if it's a float
It depends on what your definition of an integer is. Is "3.0" an integer? Or just "3"? The former is most commonly represented as a floating point number whose value happens to be a mathematical integer (but not of int type).
If you mean to include "3.0", then you can do a test which catches both "3.0" and "3":
f = float(x)
if f==int(f):
print("really an integer value")
Otherwise you can use isinstance(f, int).
(Caveat: this is easier in Python3. In Python2 there are two kinds of integers -- int and long which you have to test for separately).
The input is alway a string.
You just want to know if that string can be converted to an int or a float value. You can easily convince yourself that most(*) integer representation can be converted to float values while the symetric is not true.
So you should
try to convert to an int
if it failed try to convert to a float
if it still failed process input as a string
The rationale is that if the user typed 3.0 they probably intended that it should be a float value, else they would have typed 3.
Python integers are only limited by the available memory while float are 64 bits iEEE-754 floating point numbers. But Python is kind enough to convert integers greater to the max float values to inf. So even an integer that cannot be represented as a float would be converted with no exception

How to accurately interpret large float numbers in Python

I want to calculate additions of a very large number (type, float) and a very small number using Python 2.7.
For example:
>> x = 1546439400046560970.
>> y = 1.
>> print(int(x + y))
1546439400046561024
This is not right. Correct answer is 1546439400046560971.
I realize that the problem is due to type cast from float to int. How could I solve this problem, if I want to get the correct answer?
I realize that the problem is due to type cast from float to int.
Not really. The float itself does not store your value precisely. You can prove that this is the case by converting to a type that has more precision than a float, for example decimal.
>>> import decimal
>>> decimal.decimal(1546439400046560971.)
Decimal('1546439400046561024')
So any solution that initially stores x as a float is doomed to fail, even if you never use the int type.
One possible solution is to store your values as decimals to begin with. Remember to initialize them using strings and not floats, or else the precision will be lost.
>>> from decimal import Decimal
>>> x = Decimal("1546439400046560971")
>>> y = Decimal("1")
>>> x+y
Decimal('1546439400046560972')

Categories