-3

Actual Question

Why something like:

#Converting float to integer
a = 1.0
int(a)  # a is now 1

# Converting String to float to integer
b = '1.0'
b = float(b)  # b is now 1.0
b = int(b)  # b is now 1

works but:

a = '1.0'
a = int(a)  # this throws a ValueError (invalid literal for int() with base 10: "1.0")

Context for question

The reason I ask is because I had a problem with getting two numbers, p and q, as input and depending on:

  1. if both are integers, return p//q
  2. if at least one is a float, return p/q
  3. print a warning if either is not a valid number.

The method I used was:

p, q = input("Enter two numbers: ").split()

try:
    p = int(p)
    q = int(q)
    print("P//Q = ", p//q)
except ValueError:
    try:
        p = float(p)
        q = float(q)
        print("P/Q = ", p/q)
    except ValueError:
        print("Invalid entries for p or q.")

This seems to work, but I was surprised when entering '1.0' for one of the values threw a value error when calling int('1.0').

I did try .isdigit() and .isdecimal() methods, however both fail on the string "0.5" etc.

Edited the question for clarity on what I was actually asking. I apologize for how the problem was posted

Sea Bacon
  • 3
  • 2
  • `"0.5".isdigit()` is `False` as this is not an `int` but `"50".isdigit()` is `True` or is the issue that you want `"1.0"` to be considered and int rather than a float? – JonSG Mar 09 '23 at 15:20
  • @JonSG part of my question was why int(1.0) is valid but int("1.0") isnt. "1.0" seems like it should be able to easily be represented as an integer, but converting doesnt work – Sea Bacon Mar 09 '23 at 15:34
  • @Tomerikoo The result of the division wont always be an integer (i.e. p=3, q=2 should return 1). So you need to know if both are integers at the start to determine whether you return an int (floor division) or a float (normal division) – Sea Bacon Mar 09 '23 at 15:38
  • 2
    So is the question "Technically, why does `int()` not like strings with decimal places?" or is your question "How do I alter my code to account for that fact?" – JonSG Mar 09 '23 at 15:41
  • 1
    Suppose there are two types, `f` and `g`, that can both parse a string `x` into different values. What, then, should `int(x)` produce, `int(f(x))` or `int(g(x))`? `int` should not have to worry about deciding which type is better by looking at `x`; it should simply assume that either `x` is either an *integer* literal, or raise an error and let the caller parse `x` first. – chepner Mar 09 '23 at 15:49
  • 1
    @JonSG yeah I mainly wanted to know why int("1.0") can't convert to an integer – Sea Bacon Mar 09 '23 at 16:00

2 Answers2

0
def get_number(input_string):
    try:
        num = int(input_string)
    except ValueError:
        try:
            num = float(input_string)
        except ValueError:
            print("Invalid input: {}".format(input_string))
            return None

        if num.is_integer():
            num = int(num)

    return num


p, q = input("Enter two numbers: ").split()

p = get_number(p)
q = get_number(q)

if p is not None and q is not None:
    if isinstance(p, int) and isinstance(q, int):
        print("P//Q = ", p // q)
    else:
        print("P/Q = ", p / q)
angwrk
  • 394
  • 1
  • 8
  • That's an interesting way to check. I wanted to avoid string parsing as it seemed like it would be a pain, but checking before and after the decimal to see if both are digits is clever. I guess you could also check to see if int(parts[1])==0 to determine if the number is a float version of an integer – Sea Bacon Mar 09 '23 at 15:25
  • 1
    @SeaBacon That's already a built-in feature..... [`float.is_integer()`](https://docs.python.org/3/library/stdtypes.html#float.is_integer) – Tomerikoo Mar 09 '23 at 15:34
  • @Tomerikoo oh you're right, it's so much better – angwrk Mar 09 '23 at 15:40
  • Wouldn't it be simpler to check for `float` first? i.e. `try` to convert to float. If it errored, the input is surely bad. If not, check if it `is_integer` and convert to int if possible – Tomerikoo Mar 09 '23 at 15:45
-2
p, q = "0.5", "0.5"
def parse_to_number(n):
    try:
        return int(n)
    except:
        return float(n)
try:
    p = parse_to_number(p)
    q = parse_to_number(q)

    if isinstance(p, int) and isinstance(q, int):
        print("P//Q = ", p//q)
    else:
        print("P/Q = ", p/q)
except ValueError:
    print("Invalid entries for p or q.")
matszwecja
  • 6,357
  • 2
  • 10
  • 17