I want to validate a float value between 0 and 5 that can have the format x.xx
So 3.14 is valid, however 3.14a would be invalid.
if x <= 0 or x > 5 or not x.isdigit():
return 'error'
However, this will return error for 1.1, since there's the '.' character...
def is_valid(num):
try:
return 0 < float(num) <= 5
except ValueError:
print('error: not a valid floating point number')
return False
float will raise a ValueError if num is not a number which can be interpreted as float.
You can use a regex:
import re
validate = lambda x: re.match(r"^[0-4]\.[0-9]{2}|5\.00$", x) is not None
x = "1.21"
if not validate(x):
print('error')
This will match a string containing a number with the y.xx format, where y is in the 0-4 range and y can be any. This covers the 0.00-4.99 range. Finally, we cover 5.00 as a special case.
If you need to accept 4.0 as well, you can slightly modify the regex as
r"^[0-4]\.[0-9]{1,2}|5\.00?$"
so that the second digit becomes optional.
def is_string_a_float_between_0_and_5(s):
try:
return 0 <= float(s) <= 5
except ValueError:
return False
x = "3.14a"
try:
if float(x) <= 0 or float(x) > 5:
print('error')
except:
print('error')
I think isinstance will solve your problem
Convert your string to a float. If it fails that test then you know you don't have a number. If it converts, then you can check if it is between 0 and 5:
x = '3.14'
try:
x = float(x)
except ValueError:
return 'error'
if x <= 0 or x > 5:
return 'error'
If x is '3.14a' then it will hit the ValueError and return 'error'
You're missing a bit of information here. Are you expecting that x is a string? If that's the case, you need to cast x to a float before testing if it's between 0 and 5.
Secondly, it's considered "non-pythonic" to check your variable types. Python is a "duck typed" language, and you're not supposed to check types unless absolutely necessary. Here's a great answer about if someone misuses your function.
To answer the real question about checking if a number is between 0 and 5:
y = float(x) # Will throw exception if x is not castable to a float
if y < 0 or y > 5:
raise ValueError("Bad x parameter!")
Related
I've just started to learn python and can't get this code to work properly.
def percentage():
while True:
try:
x = int(input('First number:'))
y = int(input('Second number:'))
fraction = x/y
percentage = fraction * 100
final = "%d" % percentage
return final
except ZeroDivisionError:
pass
except ValueError:
pass
if percentage() <= 1:
print('E')
elif percentage() >= 99:
print('F')
else:
print(percentage(), "%")
The 'F' is printed only when I input x = 999 and y = 1000. Any other values just prompt the user again and again.
The code should output 'E' when the percentage function returns <= 1, 'F' when it returns >= 99 and the actual percentage number when any other value is returned.
I am getting a type error as final is a string which you then try to compare with an integer. The issue that you are asking about, however, is due to 3 calls of percentage(). Instead call it once and assign the return value a variable then run your tests against the variable:
def percentage():
while True:
try:
x = int(input('First number:'))
y = int(input('Second number:'))
return 100 * x / y
except ZeroDivisionError:
print('x')
pass
except ValueError:
print('y')
pass
p = percentage()
if p <= 1:
print('E')
elif p >= 99:
print('F')
else:
print(p, "%")
I would restructure your program so that your percentage function returns the percentage as a float instead of a string, and deal with the string formatting in your print statements.
We should also set some variable equal to the output of your function using something like p = percentage(), and then use p in your conditionals so that we don't unintentionally run percentage() multiple times from within your conditionals.
def percentage():
while True:
try:
x = int(input('First number:'))
y = int(input('Second number:'))
fraction = x/y
percentage = fraction * 100
# final = "%d" % percentage
return percentage
except ZeroDivisionError:
pass
except ValueError:
pass
p = percentage()
if p < 1:
print('E')
elif p >= 99:
print('F')
else:
print(f"{p:.2f}%")
Example program run:
First number:2
Second number:3
66.67%
I have this program where among other things I have to validate if the list of elements is composed only of integers bigger than 0, but my current validation isn't working. This is my current program:
def validateList(num):
i = 0
while i < len(num):
x = num[i]
try:
a = int(x)
if a > 0:
i += 1
return a
else:
print('Must be higher than 0,')
return validateList(num)
except:
print ('Values must be integers.')
return validateList(num)
def pedirListaAlternativos():
string = input("Input a list of numbers separated by comma and space: ")
list = string.split(', ')
print(validarLista(list))
It has to be iterative and I can only use lists and cycles, not functions.
Any help would be appreciated.
You probably want a function that returns either True or False depending on whether the list is comprised entirely of integers with values greater than zero. For example:
def isValidList(lst):
for e in lst:
try:
if int(e) <= 0:
return False
except ValueError:
return False
return True
This is an iterative solution whereas the original code seems to be attempting recursion (which is quite unnecessary)
I wrote a code
i = input()
w = input()
if i % w > 0 :
print("Yes")
which takes two integers as input. If the first is exactly divisible by the second (such as 10 and 5 or 24 and 8, but not 10 and 3 or 24 and 7) it outputs “Yes”, otherwise “No”, except when the second is zero, in which case it outputs “Cannot divide by zero”. But it caused an error. Please help me know what's wrong with this code and the answer.
Cast to integer with int() and group with parentheses
i = int(input())
w = int(input())
if (i % w) > 0:
print("Yes")
Use int to change the object type from string to integer.
To handle divide by 0 use try and except.
i = int(input())
w = int(input())
try:
if (i%w) == 0:
print("Yes")
else:
print("No")
except ZeroDivisionError:
print("second input can't be 0")
Since the modulus function returns zero when the number is a divisor, you don’t even have to use and == operator.
try:
result = “Yes” if not (i % w) else “No”
except ZeroDivisionError:
result = “Divide by zero”
print(result)
So I'm creating a program to show number systems, however I've run into issues at the first hurdle. The program will take a number from the user and then use that number throughout the program in order to explain several computer science concepts.
When explaining my first section, number systems, the program will say what type of number it is. I'm doing this by converting the string into a float number. If the float number only has '.0' after it then it converts it into a integer.
Currently I'm using this code
while CorrectNumber == False:
try:
Number = float(NumberString) - 0
print (Number)
except:
print ("Error! Not a number!")
This is useful as it shows if the user has entered a number or not. However I am unsure how to now check the value after the decimal place to check if I should convert it into a integer or not. Any tips?
If the string is convertable to integer, it should be digits only. It should be noted that this approach, as #cwallenpoole said, does NOT work with negative inputs beacuse of the '-' character. You could do:
if NumberString.isdigit():
Number = int(NumberString)
else:
Number = float(NumberString)
If you already have Number confirmed as a float, you can always use is_integer (works with negatives):
if Number.is_integer():
Number = int(Number)
Not sure I follow the question but here is an idea:
test = ['1.1', '2.1', '3.0', '4', '5', '6.12']
for number in test:
try:
print(int(number))
except ValueError:
print(float(number))
Returns:
1.1
2.1
3.0
4
5
6.12
Here is the method to check,
a = '10'
if a.isdigit():
print "Yes it is Integer"
elif a.replace('.','',1).isdigit() and a.count('.') < 2:
print "Its Float"
else:
print "Its is Neither Integer Nor Float! Something else"
This checks if the fractional-part has any non-zero digits.
def is_int(n):
try:
float_n = float(n)
int_n = int(float_n)
except ValueError:
return False
else:
return float_n == int_n
def is_float(n):
try:
float_n = float(n)
except ValueError:
return False
else:
return True
Testing the functions:
nums = ['12', '12.3', '12.0', '123.002']
for num in nums:
if is_int(num):
print(num, 'can be safely converted to an integer.')
elif is_float(num):
print(num, 'is a float with non-zero digit(s) in the fractional-part.')
It prints:
12 can be safely converted to an integer.
12.3 is a float with non-zero digit(s) in the fractional-part.
12.0 can be safely converted to an integer.
123.002 is a float with non-zero digit(s) in the fractional-part.
Regular expressions are nice for this as they can be custom tailored in case you have some edge-cases. For example:
How do you want to handle padded numbers (numbers with leading zeros). My example here includes this consideration.
Do you need to handle exponents, e.g. 2.3E12 or 2.3e12. This is not handled here.
...in other words, if your implementation doesn't agree with an assumption mine makes, you can change it.
Regular expressions work in all versions of Python (and other languages). They can be compiled for reuse, so should be pretty quick.
# Int is:
# - Only numbers that do NOT start with 0 (protect padded number strings)
# - Exactly 0
re_int = re.compile(r"(^[1-9]+\d*$|^0$)")
# Float is:
# - Only numbers but with exactly 1 dot.
# - The dot must always be followed number numbers
re_float = re.compile(r"(^\d+\.\d+$|^\.\d+$)")
These tests all pass:
def test_re_int(self):
self.assertTrue(re_int.match("1"))
self.assertTrue(re_int.match("1543"))
self.assertTrue(re_int.match("0")) # Exactly 0 is good
self.assertFalse(re_int.match("1.54"))
self.assertFalse(re_int.match("1a4"))
self.assertFalse(re_int.match("14a"))
self.assertFalse(re_int.match("a14"))
self.assertFalse(re_int.match("00")) # Ambiguous
self.assertFalse(re_int.match("0012")) # Protect padding
def test_re_float(self):
self.assertTrue(re_float.match("1.0"))
self.assertTrue(re_float.match("1.456"))
self.assertTrue(re_float.match("567.456"))
self.assertTrue(re_float.match("0.10"))
self.assertTrue(re_float.match(".10"))
self.assertFalse(re_float.match("1.0.0")) # Too many dots
self.assertFalse(re_float.match(".10.0"))
self.assertFalse(re_float.match("..034"))
self.assertFalse(re_float.match("1"))
self.assertFalse(re_float.match("0"))
self.assertFalse(re_float.match("1a4"))
self.assertFalse(re_float.match("14a"))
self.assertFalse(re_float.match("a14"))
self.assertFalse(re_float.match("1.a4"))
self.assertFalse(re_float.match("1.4a"))
self.assertFalse(re_float.match(".a14"))
Please comment if there are any caveats, missing details or regular expression improvements I can make.
Here's my gist that not only checks for positive & negative ints, but also checks for positive & negative floats. It also checks if the string is just a normal non-number.
def int_float_or_string(string):
try:
int(string) # strict and nice
except ValueError:
if is_strictly_float(string): # float() is too permissive, this is better
return "float"
else:
return "string"
else:
return "int"
def is_strictly_float(string):
if string.startswith("-"):
string = string[1:]
return "." in string and string.replace(".", "", 1).isdecimal()
int() is great for checking an integer, but float() has a problem of being too laid back in what it calls a float.
x=input("Enter a value to check it's type: ")
def checknumber(a):
try:
a=float(a)
if int(a)/a==1:
print("This is Integer")
return a
elif a/int(a)>1:
print("This is Float")
return a
except ValueError:
print("This value is String")
return str(a)
x=checknumber(x)```
I rewrite bin Mohammed's answer as follows (number also may be negative):
from numpy import nan, isnan
def is_valid_number(s):
if (s.find('-') <= 0) and s.replace('-', '', 1).isdigit():
if (s.count('-') == 0):
s_type = 'Positive Integer'
else:
s_type = 'Negative Integer'
elif (s.find('-') <= 0) and (s.count('.') < 2) and \
(s.replace('-', '', 1).replace('.', '', 1).isdigit()):
if (s.count('-') == 0):
s_type = 'Positive Float'
else:
s_type = 'Negative Float'
else:
s_type = "Not alphanumeric!"
return('{}\t is {}'.format(s, s_type))
example:
nums = ['12', '-34', '12.3', '-12.0', '123.0-02', '12!','5-6', '3.45.67']
for num in nums:
print(is_valid_number(num))
result:
12 is Positive Integer
-34 is Negative Integer
12.3 is Positive Float
-12.0 is Negative Float
123.0-02 is Not alphanumeric!
12! is Not alphanumeric!
5-6 is Not alphanumeric!
3.45.67 is Not alphanumeric!
minimal code:
from numpy import nan, isnan
def str2num(s):
if (s.find('-') <= 0) and s.replace('-', '', 1).isdigit():
return(int(s))
elif (s.find('-') <= 0) and (s.count('.') < 2) and \
(s.replace('-', '', 1).replace('.', '', 1).isdigit()):
return(float(s))
else:
return(nan)
example:
nums = ['12', '-34', '12.3', '-12.0', '123.0-02', '12!','5-6', '3.45.67']
for num in nums:
x = str2num(num)
if not isnan(x):
print('x =', x) # .... or do something else
result:
x = 12
x = -34
x = 12.3
x = -12.0
when I try this
if question.isdigit() is True:
I can type in numbers fine, and this would filter out alpha/alphanumeric strings
when I try 's1' and 's' for example, it would go to (else).
Problem is, when I put negative number such as -1, '.isdigit' counts '-' sign as string value and it rejects it. How can I make it so that '.isdigit' allows negative symbol '-'?
Here is the code. Of the thing i tried.
while a <=10 + Z:
question = input("What is " + str(n1) + str(op) + str(n2) + "?")
a = a+1
if question.lstrip("-").isdigit() is True:
ans = ops[op](n1, n2)
n1 = random.randint(1,9)
n2 = random.randint(1,9)
op = random.choice(list(ops))
if int(question) is ans:
count = count + 1
Z = Z + 0
print ("Well done")
else:
count = count + 0
Z = Z + 0
print ("WRONG")
else:
count = count + 0
Z = Z + 1
print ("Please type in the number")
Use lstrip:
question.lstrip("-").isdigit()
Example:
>>>'-6'.lstrip('-')
'6'
>>>'-6'.lstrip('-').isdigit()
True
You can lstrip('+-') if you want to consider +6 a valid digit.
But I wouldn't use isdigit, you can try int(question), it'll throw an exception if the value cannot be represented as int:
try:
int(question)
except ValueError:
# not int
Use a try/except, if we cannot cast to an int it will set is_dig to False:
try:
int(question)
is_dig = True
except ValueError:
is_dig = False
if is_dig:
......
Or make a function:
def is_digit(n):
try:
int(n)
return True
except ValueError:
return False
if is_digit(question):
....
Looking at your edit cast to int at the start,checking if the input is a digit and then casting is pointless, do it in one step:
while a < 10:
try:
question = int(input("What is {} {} {} ?".format(n1,op,n2)))
except ValueError:
print("Invalid input")
continue # if we are here we ask user for input again
ans = ops[op](n1, n2)
n1 = random.randint(1,9)
n2 = random.randint(1,9)
op = random.choice(list(ops))
if question == ans:
print ("Well done")
else:
print("Wrong answer")
a += 1
Not sure what Z is doing at all but Z = Z + 0 is the same as not doing anything to Z at all 1 + 0 == 1
Using a function to take the input we can just use range:
def is_digit(n1,op,n2):
while True:
try:
n = int(input("What is {} {} {} ?".format(n1,op,n2)))
return n
except ValueError:
print("Invalid input")
for _ in range(a):
question = is_digit(n1,op,n2) # will only return a value when we get legal input
ans = ops[op](n1, n2)
n1 = random.randint(1,9)
n2 = random.randint(1,9)
op = random.choice(list(ops))
if question == ans:
print ("Well done")
else:
print("Wrong answer")
If you do not wish to go for try... except, you could use regular expression
if re.match("[+-]?\d", question) is not None:
question = int(question)
else:
print "Not a valid number"
With try... except, it is simpler:
try:
question = int(question)
except ValueError:
print "Not a valid number"
If isdigit is must and you need to preserve the original value as well, you can either use lstrip as mentioned in an answer given. Another solution will be:
if question[0]=="-":
if question[1:].isdigit():
print "Number"
else:
if question.isdigit():
print "Number"
I have just had a similar question on edabit where I realised that negative numbers returned as False whilst using isnumeric(). I have put my solution below:
Create a function that takes a list of strings and integers, and filters out the list so that it returns a list of integers only.
def filter_list(list):
numbers = [i for i in list if str(i).isnumeric() == True]
for i in list:
try:
int(i)
if i <0:
numbers.append(i)
except ValueError:
continue
return numbers
list = [1,2,3,'a','b','c', -6, 0]
print(filter_list(list))
I am still new to Python so this is a basic attempt. Feel free to let me know if there is a much easier or better looking way.
To check if your input string is numeric or not, even in cases when you enter negative values or floats you can do this:
if string.replace('.','').replace('-','').isnumeric():
print(string + ' is a number')
If you want to check specifically if your string is a negative number you can do this:
if string[0] == '-' and string[1:].replace('.','').isnumeric():
print(string + ' is a negative number')
I know it's late, but I just stumbled appon this question and I had a similar problem wich I solved this way:
#staticmethod
def getStringToFloatOrNone(value):
if value == None:
return None
if not str(value).replace(",","").replace(".","").replace("-","").strip().isdigit():
return 0
return value if isinstance(value, float) or isinstance(value, int) else float(Helper.createViableFloatOrIntString(value))
return int(float(value)) if isinstance(value, float) or isinstance(value, int) else int(float(Helper.createViableFloatOrIntString(value)))
Just replace all the common delimitter and try if it's a digit.
If yes, get the actual value as float.
Simple way to do this using lambda,
is_numeric = lambda x: x.replace('.', '', 1).replace('-', '', 1).isdigit()
You can use this like:
if is_numeric(question):
## your code here ##
#Hurri have done something similar, but afraid it return True for values like IP addresses.