How to parse a string to a float compatible with Numba `njit()`? - python

I have some Numba accelerated code in NoPython mode using numbaa.njit().
At some point I need to parse a str (or bytes) to get a float.
In pure Python, the way I would go about it is with float(), but that does not work:
import numba as nb
#nb.njit
def str2float(text):
return float(text)
str2float("1.2")
TypingError: Failed in nopython mode pipeline (step: nopython frontend)
No implementation of function Function(<class 'float'>) found for signature:
>>> float(unicode_type)
while I would like it to produce a float with value 1.2.
The following questions are somewhat related:
this question discusses parsing to int (str/bytes-to-int)
this question discusses the opposite, i.e. the conversion of a float-to-str conversion

While this is not yet supported (as of July 2022), you can implement something manually.
Below are two versions, one for str and one for bytes.
In the process of solving the task I use a str/bytes-to-int which is used to parse str that include the exponential notation e.g. 1.0e-02 and -- potentially -- a trim() function to pre-process inputs surrounded by whitespaces ("C" whitespaces: " ", "\n", "\r", "\t", "\v").
Both are presented here and only used below.
From str
import math
import numba as nb
#nb.njit
def str2float_helper(text):
sep = ord(".")
c_min = ord("0")
c_max = ord("9")
n = len(text)
valid = n > 0
# determine sign
start = n - 1
stop = -1
sign = 1
if valid:
first = ord(text[0])
if first == ord("+"):
stop = 0
elif first == ord("-"):
sign = -1
stop = 0
# parse rest
sep_pos = 0
number = 0
j = 0
for i in range(start, stop, -1):
c = ord(text[i])
if c_min <= c <= c_max:
number += (c - c_min) * 10 ** j
j += 1
elif c == sep and sep_pos == 0:
sep_pos = j
else:
valid = False
break
return sign * number, sep_pos, valid
#nb.njit
def str2float(text):
if text == "nan" or text == "NAN" or text == "NaN":
return math.nan
exp_chars = b"eE"
exp_pos = -1
for exp_char in exp_chars:
for i, c in enumerate(text[::-1]):
c = ord(c)
if c == exp_char:
exp_pos = i
break
if exp_pos > -1:
break
if exp_pos > 0:
exp_number = str2int(text[-exp_pos:])
if exp_number is None:
exp_number = 0
number, sep_pos, valid = str2float_helper(text[:-exp_pos-1])
result = number / 10.0 ** (sep_pos - exp_number) if valid else None
else:
number, sep_pos, valid = str2float_helper(text)
result = number / 10.0 ** sep_pos if valid else None
return result
This should work similarly to float_() (defined below) which is a helper function that returns None instead of raising in case of parsing failure:
def float_(x):
try:
return float(x)
except ValueError:
return None
def is_close(x, y):
if x and not y or not x and y:
return False
else:
return x == y or math.isclose(x, y) or math.isnan(x) and math.isnan(y)
numbers = (
"", "NaN", "10", "32.1", "4123.43214e+05", "4123.43214E+05", "4123.43214e-05",
"-31", "-12.3", "-4123.43214e+05", "-4123.43214E+05", "-4123.43214e-05",
" 1321.432 \t ", "1+2", "1-2", "1e", "e1",
)
k = 24
for number in numbers:
print(f"{number!r:{k}} {float_(number)!s:{k}} {str2float(number)!s:{k}} {is_close(float_(number), str2float(number))}")
# '' None None True
# 'NaN' nan nan True
# '10' 10.0 10.0 True
# '32.1' 32.1 32.1 True
# '4123.43214e+05' 412343214.0 412343214.0 True
# '4123.43214E+05' 412343214.0 412343214.0 True
# '4123.43214e-05' 0.0412343214 0.0412343214 True
# '-31' -31.0 -31.0 True
# '-12.3' -12.3 -12.3 True
# '-4123.43214e+05' -412343214.0 -412343214.0 True
# '-4123.43214E+05' -412343214.0 -412343214.0 True
# '-4123.43214e-05' -0.0412343214 -0.0412343214 True
# ' 1321.432 \t ' 1321.432 None False
# '1+2' None None True
# '1-2' None None True
# '1e' None None True
# 'e1' None None True
# '1.1e-200' 1.1e-200 1.0999999999999995e-200 True
# '1.1e+200' 1.1e+200 1.1000000000000005e+200 True
(except for the trimming whitespaces part which can be added if needed).
Timewise, this is some 12x slower than pure Python:
%timeit -n 32 -r 32 [str2float(number) for number in numbers]
# 32 loops, best of 32: 80.3 µs per loop
%timeit -n 32 -r 32 [float_(number) for number in numbers]
# 32 loops, best of 32: 6.55 µs per loop
and hence only useful if this is needed as part of a more complex njit()-ed code.
From bytes
This is essentially a rewrite of the above to work with bytes (which typically only require skipping some ord(), because iterating bytes provides the integer representation directly) or defining a == operator because that is not available for bytes.
#nb.njit
def bytes2float_helper(text):
sep = ord(".")
c_min = ord("0")
c_max = ord("9")
n = len(text)
valid = n > 0
# determine sign
start = n - 1
stop = -1
sign = 1
if valid:
first = text[0]
if first == ord("+"):
stop = 0
elif first == ord("-"):
sign = -1
stop = 0
# parse rest
sep_pos = 0
number = 0
j = 0
for i in range(start, stop, -1):
c = text[i]
if c_min <= c <= c_max:
number += (c - c_min) * 10 ** j
j += 1
elif c == sep and sep_pos == 0:
sep_pos = j
else:
valid = False
break
return sign * number, sep_pos, valid
#nb.njit
def eqb(text_a, text_b):
len_a = len(text_a)
len_b = len(text_b)
if len_a == len_b:
for i in range(len_a):
if text_a[i] != text_b[i]:
return False
return True
else:
return False
#nb.njit
def bytes2float(text):
if eqb(text, b"nan") or eqb(text, b"NAN") or eqb(text, b"NaN"):
return math.nan
exp_chars = b"eE"
exp_pos = -1
for exp_char in exp_chars:
for i, c in enumerate(text[::-1]):
if c == exp_char:
exp_pos = i
break
if exp_pos > -1:
break
if exp_pos > 0:
exp_number = bytes2int(text[-exp_pos:])
if exp_number is None:
exp_number = 0
number, sep_pos, valid = bytes2float_helper(text[:-exp_pos-1])
result = number / 10.0 ** (sep_pos - exp_number) if valid else None
else:
number, sep_pos, valid = bytes2float_helper(text)
result = number / 10.0 ** sep_pos if valid else None
return result
The interesting bit it of this is that this has comparable speed (albeit marginally slower by some 15%) as the pure Python counterpart:
numbers = (
b"", b"NaN", b"10", b"32.1", b"4123.43214e+05", b"4123.43214E+05", b"4123.43214e-05",
b"-31", b"-12.3", b"-4123.43214e+05", b"-4123.43214E+05", b"-4123.43214e-05",
b" 1321.432 ", b"1+2", b"1-2", b"1e", b"e1", b"1.1e-200", b"1.1e+200",
)
k = 24
for number in numbers:
print(f"{number!s:{k}} {float_(number)!s:{k}} {bytes2float(number)!s:{k}} {is_close(float_(number), bytes2float(number))}")
# b'' None None True
# b'NaN' nan nan True
# b'10' 10.0 10.0 True
# b'32.1' 32.1 32.1 True
# b'4123.43214e+05' 412343214.0 412343214.0 True
# b'4123.43214E+05' 412343214.0 412343214.0 True
# b'4123.43214e-05' 0.0412343214 0.0412343214 True
# b'-31' -31.0 -31.0 True
# b'-12.3' -12.3 -12.3 True
# b'-4123.43214e+05' -412343214.0 -412343214.0 True
# b'-4123.43214E+05' -412343214.0 -412343214.0 True
# b'-4123.43214e-05' -0.0412343214 -0.0412343214 True
# b' 1321.432 ' 1321.432 None False
# b'1+2' None None True
# b'1-2' None None True
# b'1e' None None True
# b'e1' None None True
# b'1.1e-200' 1.1e-200 1.0999999999999995e-200 True
# b'1.1e+200' 1.1e+200 1.1000000000000005e+200 True
%timeit -n 32 -r 32 [bytes2float(number) for number in numbers]
# 32 loops, best of 32: 8.84 µs per loop
%timeit -n 32 -r 32 [float_(number) for number in numbers]
# 32 loops, best of 32: 7.66 µs per loop

Related

Python: Given a 2-D array, return True is every number in array is a power of two, 0, and greater than 2000. No imported libraries

Python: Given a 2-D array, create a function that will return True if every number in array is a power of two, 0 and greater than 200. No imported libraries.
Ex:
board = [[0,1,0,2],[0,0,2,4],[0,7,2001,0]]
return False
--
def is_data(board):
col= len(board[0])
row= len(board)
for c in range(col):
for r in range(row):
n= int(board[r][c])
if n > 2000:
return False
else:
while isinstance(n, int) == True:
if n % 2 != 1:
if isinstance(n, float):
return False
break
else:
n = n//2
return True
floor division isn't powers-of-two.
https://www.w3schools.com/python/trypython.asp?filename=demo_oper_floordiv
def power_of_two( num ):
while num > 1: num /= 2
if num == 1: return True
else: return False
print( power_of_two( 7 ) )
print( power_of_two( 92 ) )
print( power_of_two( 128 ) )
print( power_of_two( 4096 ) )
Output:
False
False
True
True

I need to make a EAN-13 number validity checker in Python2. I don't see why this doesn't work

inp = raw_input("Input a EAN-13 number.")
aaa = False
bbb = False
if len(inp) == 13:
bbb = True
else:
print "Error input"
exit
ean_number = int(inp)
def ean13(value_1):
mult_of_ten = 0
sum_of_digits = 0
done = False
for z in len(value_1):
if not z == 0:
if z % 2 == 0:
value_1[z] *= 3
elif not z % 2 == 0:
value_1[z] *= 1
for a in len(value_1):
sum_of_digits += value_1[a]
if sum_of_digits % 10 == 0:
result = 0
elif not sum_of_digits % 10 == 0:
while done == False:
mult_of_ten = sum_of_digits
for d in True:
mult_of_ten += d
if sum_of_digits % 10 == 0:
done == True
result = mult_of_ten - sum_of_digits
if result == value_1[12]:
print "True"
if bbb == True:
ean13(ean_number)
I really don't see why teacher can't help either.
I need to make a EAN-13 number validity checker in Python2. I don't see why this doesn't work. Can anyone help?
I have made an EAN 13 Number Validity Checker in Python2.
Hope it helps you out.
# ean = '9780201379624'
ean = raw_input("Input a EAN-13 number:\n")
err = 0
even = 0
odd = 0
check_bit = ean[len(ean)-1]#get check bit(last bit)
check_val = ean[:-1]#Get all vals except check bit
if len(ean) != 13:#Check the input length
print "Invalid EAN 13"
else:
for index,num in enumerate(check_val):#Gather Odd and Even Bits
if index%2 == 0:
even += int(num)
else:
odd += int(num)
if ((3*odd)+even+int(check_bit)) % 10 == 0:# Check if the algorithm 3 * odd parity + even parity + check bit matches
print "Valid EAN 13"
else:
print "Invalid EAN 13"

Continue while loop after return True

I am creating a function which returns True when a number(here X) is Prime.
So I am checking whether the given number is evenly divisible by integers from 2 to X-1.
But the while loop breaks when the check returns True.
Help
def is_prime(x):
n = 2
if x < 2:
return False
elif x == 2:
return True
else:
while True and n < x:
if x % n == 0:
return False
else:
n += 1
return True #--The loop is breaking here--
You code should look like this:
def is_prime(x):
n = 2
if x < 2:
return False
elif x == 2:
return True
else:
while n < x:
if x % n == 0:
return False
else:
n += 1
# Put the return True after the loop
return True
print('{}: {}'.format(10, is_prime(10)))
print('{}: {}'.format(11, is_prime(11)))
print('{}: {}'.format(0, is_prime(0)))
print('{}: {}'.format(1, is_prime(1)))
print('{}: {}'.format(2, is_prime(2)))
print('{}: {}'.format(113, is_prime(113)))
Output:
10: False
11: True
0: False
1: False
2: True
113: True
Well You used return statment in loop, so it exited from method. You need to change the logic of this loop. Check here:
Python Prime number checker

program who returns true or false whether a matrix is a magic square or not

I'm trying to make a program that returns a boolean whether a matrix is a magic square or not. I try to submit this code at my college's website, but it returns "Wrong Answer". I can't see what's wrong with it. Can you help me?
def magico(xs):
#print(soma(xs),soma2(xs),diag(xs))
if(soma(xs) == soma2(xs) == diag(xs) != -1 ):
return True
else:
return False
def soma(xs):
sant = 0
s = 0
for i in range(len(xs)):
if(s != sant):
return -1
s = 0
for j in range(len(xs)):
s = s + int(xs[i][j])
sant = s
return s
def soma2(xs):
s = 0
sant = 0
for j in range(len(xs)):
if(s != sant):
return -1
s = 0
for i in range(len(xs)):
s = s + int(xs[j][i])
sant = s
return s
def diag(xs):
s = 0
for i in range(len(xs)):
s = s + int(xs[i][i])
t = 0
for i in range(len(xs)):
t = t + int(xs[i][len(xs) - 1 - i])
if(s == t):
return s
else:
return -1
Pseudocode
magic = true
answer = sum(square)/n_rows(square)
for r in rows(square):
if sum(r) not equal to answer
magic = false
for c in columns(square):
if sum(c) not equal to answer
magic = false
d1 = principal_diagonal(square)
d2 = secondary_diagonal(square)
if sum(d1) or sum(d2) not equal to answer
magic = false
display magic
You are not checking if the matrix is square, you are not checking if the numbers in the matrix are unique. Beyond that you have a serious coding issue:
Your loops all end with
sant = s
They start with
if(s != sant):
But you have just made them equal...

Calculator which parses user input

import string
# Strength of operations:
# -> [] (brackets)
# 6 -> ~ (negative)
# 5 -> #, $, & (average, maximum, minimum)
# 4 -> %, ! (modulo, factorial)
# 3 -> ^ (power)
# 2 -> *, / (multiplication, division)
# 1 -> +, - (addition, subtraction)
def BinaryOperation(exp, idx):
""" Gets an expression and an index of an operator and returns a tuple with (first_value, operator, second_value). """
first_value = 0
second_value = 0
#Get first value
idx2 = idx -1
if idx2 == 0:
first_value = exp[idx2:idx]
else:
while (idx2 > 0) and (exp[idx2] in string.digits):
idx2 -=1
if (exp[idx2] in ("-")) or (exp[idx2] in string.digits):#-5*3
first_value = exp[idx2:idx]
else:#%5*3
first_value = exp[idx2+1:idx]
#Get second value
idx2 = idx +1
if exp[idx+1] not in string.digits: #If there is something like 1*+5, second_sign will be +.
idx2 += 1 #idx2 will begin from the char after the sign.
while (idx2 < len(exp)) and (exp[idx2] in string.digits):
idx2 += 1
second_value = exp[idx+1:idx2]
return (first_value, exp[idx], second_value)
def UnaryOperation(exp, idx):
""" Gets an expression and an index of an operator and returns a tuple with (operator, value). """
#Get value
idx2 = idx+1
if exp[idx+1] not in string.digits: #If there is something like ~-5, second_sign will be -.
idx2 += 1 #idx2 will begin from the char after the sign.
while (idx2 < len(exp)) and (exp[idx2] in string.digits):
idx2 +=1
return (exp[idx], exp[idx+1:idx2])
def Brackets(exp):
idx = 0
while idx < len(exp):
if exp[idx] == "[":
#Brackets
close_bracket = exp.find("]")
if close_bracket == -1:
raise Exception("Missing closing bracket.")
exp_brackets = exp[idx+1:close_bracket]
value = str(solve(exp_brackets))
exp = exp.replace("[" + exp_brackets + "]", value)
idx = 0 #The len has been changed, scan again.
idx += 1
return Level6(exp)
def Level6(exp):
idx = 0
while idx < len(exp):
if exp[idx] in ("~"):
#Negative
sub_exp = UnaryOperation(exp, idx)
value = ~int(sub_exp[1])
value = str(value)
exp = exp.replace(''.join(sub_exp), value)
idx = 0 #The len has been changed, scan again.
idx += 1
return Level5(exp)
def Level5(exp):
idx = 0
while idx < len(exp):
if exp[idx] in ("#", "$", "&"):
#Average, Maximum and Minimum
sub_exp = BinaryOperation(exp, idx)
first_value = int(sub_exp[0])
second_value = int(sub_exp[2])
if sub_exp[1] == "#":
value = (first_value + second_value)/2
if sub_exp[1] == "$":
value = first_value if first_value > second_value else second_value
if sub_exp[1] == "&":
value = first_value if first_value < second_value else second_value
value = str(value)
exp = exp.replace(''.join(sub_exp), value)
idx = 0 #The len has been changed, scan again.
idx += 1
return Level4(exp)
def Level4(exp):
idx = 0
while idx < len(exp):
if exp[idx] in ("%","!"):
#Modulo and Factorial
if exp[idx] == "%":
sub_exp = BinaryOperation(exp, idx)
value = int(sub_exp[0]) % int(sub_exp[2])
if exp[idx] == "!":
sub_exp = UnaryOperation(exp, idx)
value = reduce(lambda x,y:x*y, range(1, int(sub_exp[1])+1))
value = str(value)
exp = exp.replace(''.join(sub_exp), value)
idx = 0 #The len has been changed, scan again.
idx += 1
return Level3(exp)
def Level3(exp):
idx = 0
while idx < len(exp):
if exp[idx] in ("^"):
#Power
sub_exp = BinaryOperation(exp, idx)
value = int(sub_exp[0]) ** int(sub_exp[2])
value = str(value)
exp = exp.replace(''.join(sub_exp), value)
idx = 0 #The len has been changed, scan again.
idx += 1
return Level2(exp)
def Level2(exp):
idx = 0
while idx < len(exp):
if exp[idx] in ("*", "/"):
#Multiplication and Division
sub_exp = BinaryOperation(exp, idx)
if sub_exp[1] == "*":
value = int(sub_exp[0]) * int(sub_exp[2])
if sub_exp[1] == "/":
value = int(sub_exp[0]) / int(sub_exp[2])
value = str(value)
exp = exp.replace(''.join(sub_exp), value)
idx = 0 #The len has been changed, scan again.
idx += 1
return Level1(exp)
def Level1(exp):
idx = 0
while idx < len(exp):
if (exp[idx] in ("+", "-")) and (idx != 0):
#Addition and Subtraction
sub_exp = BinaryOperation(exp, idx)
if sub_exp[1] == "+":
value = int(sub_exp[0]) + int(sub_exp[2])
if sub_exp[1] == "-":
value = int(sub_exp[0]) - int(sub_exp[2])
value = str(value)
exp = exp.replace(''.join(sub_exp), value)
idx = 0 #The len has been changed, scan again.
idx += 1
return exp
def solve(exp):
exp = Brackets(exp)
return float(exp) if "." in exp else int(exp)
def remove_whitespace(exp):
""" Gets a string and removes all whitespaces and tabs """
exp = exp.replace(" ", "")
exp = exp.replace("\t", "")
return exp
while True:
exp = raw_input("")
exp = remove_whitespace(exp)
print solve(exp)
I have written this program after a lot of effort, and I was wondering about the efficiency of that solution and if it's neat.
So my question is, how plain is this program and is there any better way to rewrite it?
just for the point.
>>> eval(raw_input("input calculation: "))
input calculation: 1+1
2
>>> eval(raw_input("input calculation: "))
input calculation: (6*4^2)
26
>>> eval(raw_input("input calculation: "))
input calculation: (3/2.3)*4
5.2173913043478262
for an innocent program, you can use eval
but you really shouldn't use it ever. its only real use is confusing people, and being a fun novelty if you write programs fro yourself and decide you want a calculator.
there are many ways to write a calculator function.
try some of these other answers:
Python creating a calculator
Basic calculator program in python
python calculator program
If you want to check out some custom class-based evaluation engines in Python, these might help you:
Expression Evaluator (version 1 with source)
Math Evaluator (version 2 with source)
again = True
answer = ""
while again is True:
try:
expression = raw_input("Enter your expression: ")
found = False
oper = -1
operator1 = 0
operator2 = 0
while found==False:
if (expression.find("+")>0 and expression.find("+")<len(expression)-1):
found = True
oper = expression.find("+")
operator1 = float(expression[:oper])
operator2 = float(expression[oper+1:])
print "{} + {} = {}".format(operator1,operator2,operator1+operator2)
elif(expression.find("-")>0 and expression.find("-")<len(expression)-1):
found = True
oper = expression.find("-")
operator1 = float(expression[:oper])
operator2 = float(expression[oper+1:])
print "{} - {} = {}".format(operator1,operator2,operator1-operator2)
elif(expression.find("*")>0 and expression.find("*")<len(expression)-1):
found = True
oper = expression.find("*")
operator1 = float(expression[:oper])
operator2 = float(expression[oper+1:])
print "{} * {} = {}".format(operator1,operator2,operator1*operator2)
elif(expression.find("/")>0 and expression.find("/")<len(expression)-1):
found = True
oper = expression.find("/")
operator1 = float(expression[:oper])
operator2 = float(expression[oper+1:])
print "{} / {} = {}".format(operator1,operator2,operator1/operator2)
else:
oper = -1
found = False
print "Incorrect expression, please try again"
break
again = False
answer = raw_input("Try again?: ")
if(answer == "y" or answer=="yes" or answer =="Y" or answer == "YES"):
again = True
else:
again = False
print "Thank you for playing! See you next time."
break
except:
print "Failed, check your expression and try again"

Categories