简体   繁体   中英

Python: format negative number with parentheses

Is there a way to use either string interpolation or string.format to render negative numbers into text formatted using parentheses instead of "negative signs"?

Ie -3.14 should be (3.14) .

I had hoped to do this using string interpolation or string.format rather than needing an import specifically designed for currencies or accounting.

Edit to clarify: Please assume the variable to be formatted is either an int or a float . Ie while this can be done with regular expressions (see good answers below), I was thinking this would be a more native operation for Python's formatting functionality.

So to be clear:

import numpy as np
list_of_inputs = [-10, -10.5, -10 * np.sqrt(2), 10, 10.5, 10 * np.sqrt(2)]
for i in list_of_inputs:
    # your awesome solution goes here

should return:

(10)
(10.5)
(14.14)
10
10.5
14.14

Clearly there is some flexibility about that last one. I had hoped the "put negative numbers in parentheses" would be a natural argument of string interpolation or string.format so that I could use other formatting language while setting the display style of negative numbers.

如果您只需要处理可能为负的数字输入:

print '{0:.2f}'.format(num) if num>=0 else '({0:.2f})'.format(abs(num))

This is what subclassing the formatter class is for. Try the following:

import string
class NegativeParenFormatter(string.Formatter):
    def format_field(self, value, format_spec):
        try:
            if value<0:
                return "(" +  string.Formatter.format_field(self, -value, format_spec) + ")"
            else:
                return string.Formatter.format_field(self, value, format_spec)
        except:
            return string.Formatter.format_field(self, value, format_spec)

f = NegativeParenFormatter()
print f.format("{0} is positive, {1} is negative, {2} is a string", 3, -2, "-4")

this prints:

'3 is positive, (2) is negative, -4 is a string'

Pandas has a display option for floats and numpy has a display option for any dtype:

In [11]: df = pd.DataFrame([[1., -2], [-3., 4]], columns=['A', 'B'])

Note: A is a float column, B is an int column.

We can just write a simple formatter depending on the sign of the number:

In [12]: formatter = lambda x: '(%s)' % str(x)[1:] if x < 0 else str(x)

In [13]: pd.options.display.float_format = formatter

In [14]: df  # doesn't work for the int column  :(
Out[14]:
      A  B
0   1.0  2
1 (3.0)  4

In [15]: df.astype(float)
Out[15]:
      A     B
0   1.0 (2.0)
1 (3.0)   4.0

You can also configure numpy's print options:

In [21]: df.values # float
Out[21]:
array([[1., 2.],
       [3., 4.]])

In [22]: df['B'].values # int
Out[22]: array([2,  4])

In [23]: np.set_printoptions(formatter={'int': formatter, 'float': formatter})

In [24]: df.values # float
Out[24]:
array([[1.0, (2.0)],
       [(3.0), 4.0]])

In [25]: df['B'].values # int
Out[25]: array([(2), 4])

Note: this doesn't change the way the data is stored, just the way you view it.

Your easiest approach would be to use a trinary.

num = -3.14
output = "({})".format(math.fabs(num)) if num < 0 else "{}".format(num)

I can't remember if this works with a straight print statement instead of an assignment. I will check this when I get by an interpreter.

Thanks LartS for 3.x confirmation: I further confirmed against(3.x and 2.x)

print("({})".format(math.fabs(num)) if num < 0 else "{}".format(num))

Does work

Maybe you're looking for something like this

float = -3.14
num=  "(%(key)s)" %{ 'key': str(abs(float))} if float < 0 else str(float)

您可以在Python print语句中使用条件:

print "%s%d%s" % ( "(" if (i<0) else(""), i, ")" if (i<0) else("") )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM