0

I aim to print a list of every element inside a user-inputted list. The outputted list identifies symbols as strings, and numbers as floats, to basically compare elements as floats and strings. If the number in the list is already a float, the output is not printed properly.

expression_list = []
expression = "(3.1+2)*5"

for index in expression:
    try: 
        float_index = float(index)
        expression_list.append(float_index)
    except ValueError:
        expression_list.append(index)
print(expression_list)     

I expect the output to be ['(', 3.1, '+', 2.0, ')', '*', 5.0] instead I get ['(', 3.0, '.', 1.0, '+', 2.0, ')', '*', 5.0]

j.doe
  • 662
  • 4
  • 19
Pikkon
  • 3
  • 1
  • 2
    I voted to reopen, because the duplicate link, which concerns floats in Python, seems to have nothing to do with the OP, which is about parsing an arithmetic expression into logical components. – Tim Biegeleisen May 13 '19 at 05:24
  • @tripleee Yes, I too do not believe the marked duplicate answers the question. – iz_ May 13 '19 at 05:28
  • Thanks for the ping and sorry for the wrong duplicate. I'll see if I can find a better one. – tripleee May 13 '19 at 05:45

2 Answers2

2

I would use re.findall here:

expression = "(3.1+2)*5"
output = re.findall(r'[()]|[^\w]+|(?:\d+(?:\.\d+)?)', expression)
print(output)

['(', '3.1', '+', '2', ')', '*', '5']

The pattern used is:

[()] | [^\w]+ | (?:\d+(?:\.\d+)?)

This matches:

[()]              an opening or closing parenthesis, as a separate match
[^\w]             any other non word character
(?:\d+(?:\.\d+)?  a number, with or without a decimal component
Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360
1

This is happening because your for loop for index in expression: iterates through every character of the string, so it is not checking if 3.1 is a float, it checks if 3 is a float and 1 is a float by converting it, and float('3')=3.0, hence you see the result.

In [8]: expression_list = [] 
   ...: expression = "(3.1+2)*5" 
   ...:  
   ...:  
   ...: for index in expression: 
   ...:     print(index) 
   ...:                                                                                                                                                                           
(
3
.
1
+
2
)
*
5

Perhaps you can split the strings in a manner which extract out the floats and the operators and brackets, which Tim's answer has provided to you.

Assuming you have that output, your code will work as expected

import re

expression_list = []
expression = "(3.1+2)*5"

literals = re.findall(r'[()]|[^\w]+|(?:\d+(?:\.\d+)?)', expression)

for index in literals:
    try:
        float_index = float(index)
        expression_list.append(float_index)
    except ValueError:
        expression_list.append(index)
print(expression_list)

The output will be ['(', 3.1, '+', 2.0, ')', '*', 5.0] as you expected!

Devesh Kumar Singh
  • 20,259
  • 5
  • 21
  • 40