Convert a number enclosed in parentheses (string) to a negative integer (or float) using Python?

Question:

In Python, what is the simplest way to convert a number enclosed in parentheses (string) to a negative integer (or float)?

For example, ‘(4,301)’ to -4301, as commonly encountered in accounting applications.

Asked By: silvernightstar

||

Answers:

The simplest way is:

my_str = "(4,301)"
num = -int(my_str.translate(None,"(),"))
Answered By: Crowman

Since you are reading from a system that put in thousands separators, it’s worth mentioning that we are not using them the same way all around the world, which is why you should consider using a locale system. Consider:

import locale
locale.setlocale( locale.LC_ALL, 'en_US.UTF-8' )
my_str = "(4,301)"
result = -locale.atoi(my_str.translate(None,"()"))
Answered By: mogul

Assuming just removing the , is safe enough, and you may wish to apply the same function to values that may contain negative numbers or not, then:

import re
print float(re.sub(r'^((.*?))$', r'-1', a).replace(',',''))

You could then couple that with using locale as other answers have shown, eg:

import locale, re

locale.setlocale(locale.LC_ALL, 'en_GB.UTF-8')
print locale.atof(re.sub('^((.*?))$', r'-1', a))
Answered By: Jon Clements

This code could be a little bit longer, but straight forward and easy to maintain

from pyparsing import Word, nums, OneOrMore

integer = Word(nums)

text = "blah blah (4,301) blah blah " 

parser = OneOrMore(integer)

iterator = parser.scanString( text )

try:
    while True:
        part1 =  iterator.next()
        part2 =  iterator.next()
except:
    x =  part1[0][0][0] + '.' +part2[0][0][0]
    print -float(x)

Produces: -4.301

Answered By: securecurve

Presumably you want to handle positive numbers as well as negative, which is missing from many of the answers thus far. I’m going to add a bit to the answer from mogul.

import locale
locale.setlocale( locale.LC_ALL, '')
my_str = '( 4,301 )'
positive = my_str.translate(None, '()')
result = locale.atoi(positive) if positive == my_str else -locale.atoi(positive)
Answered By: Mark Ransom

For Python 3.6, and also handles ‘-‘ as 0, and strips excess empty spaces:

def clean_num(num_string):
    bad_chars = '(),-'
    translator = str.maketrans('', '', bad_chars)
    clean_digits = num_string.translate(translator).strip()

    if clean_digits == '':
        return 0
    elif '(' in num_string:
        return -float(clean_digits)
    else:
        return float(clean_digits) 
Answered By: yl_low

For localized numbers, I use this:

def clean_number(text):
    import locale
    locale.setlocale(locale.LC_NUMERIC, "Portuguese_Brazil.1252")
    tbl = str.maketrans('(', '-', 'R$ )')
    return locale.atof(text.translate(tbl))

Works with Python 3.8.
The first parenthesis is replaced with the minus sign, the second is removed.
Also removes spaces and the monetary sign.

Answered By: Julio Batista Silva

As of today, the top answer is specific to Python 2. I tried editing it, but the queue is full.

For my_str = "(4,301)", the top answer advises:

num = -int(my_str.translate(None,"(),"))

For Python 3, you would instead use one of the following:

translate_table = dict({ord(i): None for i in '(),'})
num = -int(my_str.translate(translate_table))

or, more simply

num = -int(my_str.translate({ord(i): None for i in "(),"}))

If you’re curious, the change is necessary for two reasons:

  1. str.translate() now expects a single argument.

  2. The str type contains Unicode. This is why each key in the dictionary is first passed to ord: this function accepts a given Unicode character and returns the Unicode code point for it:

     >>> ord('(')
     40
    
Answered By: iff_or
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.