Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it not possible to convert "1.7" to integer directly, without converting to float first?

When I type int("1.7") Python returns error (specifically, ValueError). I know that I can convert it to integer by int(float("1.7")). I would like to know why the first method returns error.

like image 426
user3140972 Avatar asked Oct 13 '15 22:10

user3140972


People also ask

Can 1.7 be an integer?

Obviously, "1.7" does not represent an integer literal in radix base. If you want to know why the python dev's decided to limit themselves to integer literals in radix base, there are a possible infinite number of reasons and you'd have to ask Guido et.

Why would you use an integer instead of a float?

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.

What will happen if you cast a float to an integer 1 point?

Casting a float to an integer truncates the value, so if you have 3.999998 , and you cast it to an integer , you get 3 . The way to prevent this is to round the result.

How would you convert float into integers?

A float value can be converted to an int value no larger than the input by using the math. floor() function, whereas it can also be converted to an int value which is the smallest integer greater than the input using math. ceil() function.


Video Answer


4 Answers

From the documentation:

If x is not a number or if base is given, then x must be a string or Unicode object representing an integer literal in radix base ...

Obviously, "1.7" does not represent an integer literal in radix base.

If you want to know why the python dev's decided to limit themselves to integer literals in radix base, there are a possible infinite number of reasons and you'd have to ask Guido et. al to know for sure. One guess would be ease of implementation + efficiency. You might think it would be easily for them to implement it as:

  1. Interpret number as a float
  2. truncate to an integer

Unfortunately, that doesn't work in python as integers can have arbitrary precision and floats cannot. Special casing big numbers could lead to inefficiency for the common case1.

Additionally, forcing you do to int(float(...)) has the additional benefit in clarity -- It makes it more obvious what the input string probably looks like which can help in debugging elsewhere. In fact, I might argue that even if int would accept strings like "1.7", it'd be better to write int(float("1.7")) anyway for the increased code clarity.

1Assuming some validation. Other languages skip this -- e.g. ruby will evaluate '1e6'.to_i and give you 1 since it stops parsing at the first non-integral character. Seems like that could lead to fun bugs to track down ...

like image 178
mgilson Avatar answered Sep 27 '22 19:09

mgilson


We have a good, obvious idea of what "make an int out of this float" means because we think of a float as two parts and we can throw one of them away.

It's not so obvious when we have a string. Make this string into a float implies all kinds of subtle things about the contents of the string, and that is not the kind of thing a sane person wants to see in code where the value is not obvious.

So the short answer is: Python likes obvious things and discourages magic.

like image 34
Chad Miller Avatar answered Sep 27 '22 20:09

Chad Miller


Here is a good description of why you cannot do this found in the python documentation.

https://docs.python.org/2/library/functions.html#int

If x is not a number or if base is given, then x must be a string or Unicode object representing an integer literal in radix base. Optionally, the literal can be preceded by + or - (with no space in between) and surrounded by whitespace. A base-n literal consists of the digits 0 to n-1, with a to z (or A to Z) having values 10 to 35. The default base is 10. The allowed values are 0 and 2-36. Base-2, -8, and -16 literals can be optionally prefixed with 0b/0B, 0o/0O/0, or 0x/0X, as with integer literals in code. Base 0 means to interpret the string exactly as an integer literal, so that the actual base is 2, 8, 10, or 16.

Basically to typecast to an integer from a string, the string must not contain a "."

like image 37
digitaLink Avatar answered Sep 27 '22 21:09

digitaLink


Breaks backwards-compatibility. It is certainly possible, however this would be a terrible idea since it would break backwards-compatibility with the very old and well-established Python idiom of relying on a try...except ladder ("Easier to ask forgiveness than permission") to determine the type of the string's contents. This idiom has been around and used since at least Python 1.5, AFAIK; here are two citations: [1] [2]

s = "foo12.7"
#s = "-12.7"
#s = -12

try:
    n = int(s) # or else throw an exception if non-integer...
    print "Do integer stuff with", n
except ValueError:
    try:
        f = float(s) # or else throw an exception if non-float...
        print "Do float stuff with", f
    except ValueError:
        print "Handle case for when s is neither float nor integer"
        raise # if you want to reraise the exception

And another minor thing: it's not just about whether the number contains '.' Scientific notation, or arbitrary letters, could also break the int-ness of the string. Examples: int("6e7") is not an integer (base-10). However int("6e7",16) = 1767 is an integer in base-16 (or any base>=15). But int("6e-7") is never an int.

(And if you expand the base to base-36, any legal alphanumeric string (or Unicode) can be interpreted as representing an integer, but doing that by default would generally be a terrible behavior, since "dog" or "cat" are unlikely to be references to integers).

like image 35
smci Avatar answered Sep 27 '22 20:09

smci