Limit number quantity in an input

Asked

Viewed 1,177 times

-1

I am making a basic program that reverses numbers (if the user type 123, the program returns 321), but the user can enter only 3 numbers, if you pass that the program has to ask the user to type again the value.

na = input('Digite 3 números')
an = na [::-1]
print('o valor invertido é',an)

I want to know what I should use to limit the number on input.

  • 1

    "the user can enter only 3 numbers" - that means exactly 3 or at most 3? (I know it sounds silly, and the answer accepts, looks like which is at most 3 even, but try not to leave the text ambiguous, otherwise people will only hit the answer "in the kick").

  • 1

    And if it’s typed 001, this corresponds to the number 1, so the inverse should be 1 or 100? This is another detail that seems stupid and pedantic, but it is important to know if you want to invert the typed characters - as long as they are digits - or if you want to invert the digits of the numerical value (which in most cases is the same thing, but in the case of 001 makes a difference)

  • 1

    As described today you must accept exactly 3 digits and the value 001 should not be accepted, because it asks to invert numbers, no strings numerically; numerically speaking 001 is 1 and has only one digit.

  • Nathanael, enjoying, all I said below about isdigit also goes for another question from you (there can also give error, depending on what is typed, since you use int if isdigit return True)

2 answers

3


I know it’s a "basic program" you’re probably doing to train (or just an exercise you’ve been given), but anyway it’s an opportunity to discuss and delve into some points.


Given the description of the problem:

I’m making a basic program that reverses numbers (if the user type 123, the program returns 321), but the user can type only 3 numbers.

That is, first the user types something. Then you check if this something is a number with only 3 digits and reverses them.

Here comes the first doubt: the text implies that the number must have exactly 3 digits, right? Or is it at most 3 digits? Depending on what, the solution will be different.

For example, if you want to validate that it is a number you have exactly 3 digits, one option is to do so:

while True:
    try:
        n = int(input('digite um número de 3 dígitos: '))
        if 100 <= n <= 999: # é um número de 3 dígitos
            break
        print('O número deve ter 3 dígitos')
    except ValueError:
        print('Não foi digitado um número')

# calcula o inverso (fora do while)

I mean, first I try to convert what was typed to number, using int(). If a number hasn’t been typed, it launches a ValueError and the code falls on except, displaying the respective message. Then the loop continues, asking to type again.

If a number has been typed, just see if it is between 100 and 999 (ie if it is a number of exactly 3 digits). In this case, it enters the if, and the break interrupting the loop while. Then out of the while, you reverse the digits of the number (below we will see how to do this).


But if you want a number with at most 3 digits, then the test could be if n <= 999. Although this test also considers zero to be valid. Oh, and also considers negative numbers, then maybe it should be if 0 < n <= 999, so only numbers greater than zero are valid. But -123 also not a 3 digit number? In this case, the condition should be if 100 <= abs(n) <= 999 (to function abs() returns the value of the unsigned number, so we can consider negative numbers as well). Which one to use? It depends on what you need, and which cases you will consider valid.

It seems a stupid and unimportant detail ("Dude, it’s just an exercise, whatever"), But when it comes to programming real systems, details like this can make all the difference. Imagine a payment system that under certain conditions only accepts exactly 3 installments, but you make a code that accepts at most 3 (or vice versa). Or a code that accepts zero or -10 parcels (does it make sense for the number of parcels to be negative?). From a stupid detail, this becomes a serious mistake, which can give problems when users are making payments. So when a customer says that "my system must accept payments in only 3 installments", it costs nothing to ask if he meant "exactly 3" or "at most 3". I know it’s "just an exercise," but exercises are also meant to... exercise reasoning and also mindset, and think about these special cases, exceptions, strange situations that can go wrong and everything else, all this is part of professional life in our area, so it’s important to get used to thinking like this from now on.

Well, once defined the criterion for considering what is a valid number (choose the one that makes the most sense, depending on the context), let’s see how to invert it.


Reversing the digits

Here is a parenthesis to speak of two concepts: value and representation of value.

A number is an idea, a concept: it represents a numerical value... that can correspond to several different things, depending on the context (among the most common uses, we have quantities, punctuation, measurements, but there are also negative numbers that may represent a debt or negative balance, etc.). Number 5, for example, represents the idea of a specific value (any five "things").

But that same value (the 5) can be represented verbatim in different ways: as the digit "5", as "5.0", as the texts "five", "five" (in English), "五" (in Japanese), etc. All these forms are different representations of the same number (of the same value).

That said, what exactly do you want to reverse? The numerical value, or textual representation of that numerical value (the string containing the digits representing that number)?

If the user type 001, For example, do you consider it to be 3 digits? If we are thinking in terms of "textual representation of the numeric value" (i.e., a string in a given format representing a number), then we can consider that yes, the string "001" contains 3 digits (and in this case, just use len(string) to know the number of digits - plus methods like isnumeric() or isdigit() to check if they are numbers, about which we will already talk about below). And in this case, by reversing the digits (using string[::-1], as already suggested), the result would be 100.

But if we are thinking in terms of numerical values (regardless of their textual representation), then 001 actually corresponds to the number 1 (its numerical value is 1, independent of its textual representation). And 1 is not a 3-digit number, so depending on the criteria chosen above (exactly 3 or at most 3), it may or may not be accepted as a valid number. And if valid, when reversing the digits of 1, the result would also be 1.

That is, what do you really want to reverse? If it is the text typed by the user (provided that the text has only numbers), then it would be enough to adapt what was done in the another answer:

while True:
    try:
        texto = input('digite um número de 3 dígitos: ')
        if texto.isnumeric() and len(texto) == 3: # é um "número" de 3 dígitos
            break # sai do loop
        print('O número deve ter 3 dígitos')
    except ValueError:
        print('Não foi digitado um número')

print(texto[::-1]) # imprime invertido

In this case, I am considering that you chose as a criterion "has exactly 3 digits". The above code considers that 001 inverted is 100, and 1 or 01 are invalid.

But if you want to consider the numerical value (and not the exact text that the user typed), there is different:

while True:
    try:
        n = int(input('digite um número de 3 dígitos: '))
        if 100 <= n <= 999: # é um número de 3 dígitos
            break # sai do loop
        print('O número deve ter 3 dígitos')
    except ValueError:
        print('Não foi digitado um número')

# invertendo
inverso = 0
while n > 0:
    inverso = inverso * 10 + n % 10
    n //= 10

print(inverso)

Yes, I invert the digits using a mathematical algorithm, instead of converting the number to string and inverting. The difference occurs in cases like 100, whose reverse will be 1 (and not 001, because I’m considering the numerical value, not its textual representation, and so the zeros on the left are irrelevant).

But in case you want to reverse negative numbers (-123 results in -321, and -100 results in -1), just change the if within the while for if 100 <= abs(n) <= 999 (as explained above) and inversion algorithm for:

x = abs(n)
inverso = 0
while x > 0:
    inverso = inverso * 10 + x % 10
    x //= 10
if n < 0:
    inverso *= -1

So what is the right answer after all? As the question was asked, it is debatable (so much so that the other answers understood one thing, but in the comments understood another), and I decided to leave several options precisely to show that the first step to have a correct program is to define well the problem, the requirements, what can and what cannot, how should be the inputs and outputs, etc. Even if it is "just an exercise", "just a little program to train", if you do not define very well what you want to do, no answer will be certain (or anything will serve, since "whatever").


About isnumeric

It has been suggested to use the method isnumeric() to check if the string has only numbers. In fact, if the user type things like 123 and 000, this method works. But the problem is that it is quite comprehensive, and does not consider only the digits from 0 to 9. There are multiple characters defined by Unicode that isnumeric() also considers as "numbers" (see here), but not necessarily a 3-digit number (int() will launch a ValueError, even with isnumeric() returning True).

An example is the character ½ (VULGAR FRACTION ONE HALF), that with isnumeric() returns True, but when converting to number with int(), makes a mistake:

print('½'.isnumeric()) # True
print(int('½')) # ValueError

See here this code running.

That is, depending on how you want to make your code (consider numerical value or textual representation), using one or another approach can give different results: if you use isnumeric() with the string '½' and invert it with texto[::-1], "works", if you try to convert it to number using int(), makes a mistake. Again, I know that "it’s just an exercise", but if the user can type anything, your program has to be prepared to validate and only proceed if you have valid data.

Another option would be to use the method isdigit(), which is a little less comprehensive than isnumeric() (for example, '½'.isdigit() returns False). But there are also cases where isdigit() returns True but the conversion with int() gives error, such as with the character ² (SUPERSCRIPT TWO) - note that it is a "2", only smaller and placed "up" (is used for example to write numbers squared - ex: 3² = 9):

print('½'.isdigit()) # False
print('²'.isdigit()) # True
print(int('²')) # ValueError

See here this code running.

That is, depending on what you define as "digits", how much of these can be accepted (exactly X or at most X) and what you want to reverse (the numerical value or "the exact text the user typed"), the solution will be different. The other answers reverse anything (none of them is checking whether it has been typed only numbers, which for me is one of the main points of the question, and consequently of the solution) and also accept an empty string (when the user only gives one ENTER in the input()) and display the "inverted digits" of the empty string (i.e., show the message O valor invertido é ).

Maybe I’m being too rigid and "It’s just an exercise, you don’t need it", but again I say that it is important to think about these cases, because in real systems this is something that you will have to always think about. So get used from now on to validate the data you receive, even more so if the user can type anything. And always consult the documentation and understand the implication of using any functions/methods/Apis, because as you can see, use isdigit(), isnumeric() or int() may give different results depending on the case.

Another example is when there are spaces before or after the numbers.
For example, if the user types 123 . Use isnumeric() or isdigit(), the result will be False, but use int(), it converts correctly to the number 123 (see here). Of course you can fix it using texto.strip(), that removes these spaces, but this is one more case that the other answers don’t handle (if the user type 3 spaces, they accept and invert the string anyway).


In the end, all this is to say that it can always be complicated, and that you can’t trust anything the user types, and it is interesting that your program is prepared to handle unwanted/invalid data. Of course you will not write validations for all the possible and imaginable cases, but accepting anything also does not give. If the program wants to invert numbers, the least you should do is check if a number has been typed.

  • 1

    Wow, I didn’t know that isnumeric() returned True also for other kkk characters. It turned out that your answer also showed me new things xD

  • @Jeanextreme002 If the world were only in ASCII, everything would be simpler, right? After they invented Unicode, no code that handles characters is obvious... :-(

1

Use the function len(seq). This function counts how many elements a sequence (strings, lists, tuples, etc...) has, for example:

while True:
    nums = input(" Digite 3 números:")
    if len(nums) > 3:
        print(" Você deve digitar somente 3 números!")
        continue
    break
print("O valor invertido é %s."%nums[::-1])

Extra detail:

This program does not prevent the user from typing letters and other characters other than numbers. So if you want, you can use the method isnumeric() to know if the user input has only numbers.

  • 2

    This answer is wrong, it is not requiring you to type 3 digits. It is sad to see a clearly wrong answer accepted as if it were right. Doing wrong and saying you can do right doesn’t make it right.

  • I’m sorry, but I don’t understand where the answer is wrong. What he wanted was a way to ensure that the user typed at most 3 numbers. I tested the answer code and it’s working perfectly. The extra detail I left there is for him to improve the code if he wants to prevent the user from typing other things than numbers. If you can point out to me the error of the answer, I really appreciate.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.