格式化数字因此它们在小数点上对齐

时间:2015-09-27 13:26:01

标签: python formatting output

在Python中,我需要格式化数字,使它们在小数点上对齐,如下所示:

  4.8
 49.723
456.781
-72.18
  5
 13

有没有一种直截了当的方法来做到这一点?

11 个答案:

答案 0 :(得分:5)

我不认为有一种直截了当的方法,因为你需要在开始打印之前知道所有数字中小数点的位置。 (我刚刚看了一下Caramiriel的链接,以及该页面的一些链接,但我找不到任何特别适用于这种情况的内容)。

所以看起来你必须做一些基于字符串的检查&操纵列表中的数字。例如,

def dot_aligned(seq):
    snums = [str(n) for n in seq]
    dots = [s.find('.') for s in snums]
    m = max(dots)
    return [' '*(m - d) + s for s, d in zip(snums, dots)]

nums = [4.8, 49.723, 456.781, -72.18]

for s in dot_aligned(nums):
    print(s)

<强>输出

  4.8
 49.723
456.781
-72.18

如果你想处理float的列表,其中混合了一些普通的int,那么这种方法会变得有点混乱。

def dot_aligned(seq):
    snums = [str(n) for n in seq]
    dots = []
    for s in snums:
        p = s.find('.')
        if p == -1:
            p = len(s)
        dots.append(p)
    m = max(dots)
    return [' '*(m - d) + s for s, d in zip(snums, dots)]

nums = [4.8, 49.723, 456.781, -72.18, 5, 13]

for s in dot_aligned(nums):
    print(s)

<强>输出

  4.8
 49.723
456.781
-72.18
  5
 13

<强>更新

正如Mark Ransom在评论中指出的那样,我们可以使用int简化处理.split

def dot_aligned(seq):
    snums = [str(n) for n in seq]
    dots = [len(s.split('.', 1)[0]) for s in snums]
    m = max(dots)
    return [' '*(m - d) + s for s, d in zip(snums, dots)]

答案 1 :(得分:3)

如果您知道所需的精度(小数点后的数字),并且不介意使用整数时尾随零,则可以在Python 3.6中使用新的f-string({ {3}}):

numbers = [4.8, 49.723, 456.781, -72.18, 5, 13]

for number in numbers:
    print(f'{number:9.4f}')

打印:

  4.8000
 49.7230
456.7810
-72.1800
  5.0000
 13.0000

答案 2 :(得分:2)

修复小数位

import decimal

numbers = [4.8, 49.723, 456.781, 50, -72.18, 12345.12345, 5000000000000]

dp = abs(min([decimal.Decimal(str(number)).as_tuple().exponent for number in numbers]))
width = max([len(str(int(number))) for number in numbers]) + dp + 1 #including .

for number in numbers:
    number = ("{:"+str(width)+"."+str(dp)+"f}").format(number)
    print number.rstrip('0').rstrip('.') if '.' in number else number

根据要求更正考虑宽度:

numbers = [4.8, 49.723, 456.781, 50, -72.18]
width = max([len(str(number)) for number in numbers]) + 1
for number in numbers:
    number = ("{:"+str(width)+".4f}").format(number)
    print number.rstrip('0').rstrip('.') if '.' in number else number

编辑:如果要包含整数

numbers = [4.8, 49.723, 456.781, 50, -72.18]

for number in numbers:
    number = "{:10.4f}".format(number)
    print number.rstrip('0').rstrip('.') if '.' in number else number
numbers = [4.8, 49.723, 456.781, -72.18]

for number in numbers:
    print "{:10.4f}".format(number).rstrip('0')

答案 3 :(得分:1)

如果你可以接受一些前导零,你可以使用它:

numbers = [ 4.8,  49.723, 456.781, -72.18]
    for x in numbers:
    print "{:10.3f}".format(x)

如果你不喜欢前导零,你可以这样使用正则表达式:

Decimal alignment formatting in Python

然而,最佳解决方案应该是在小数点前后分别格式化字符串(numstring赋值):

numbers = [ 4.8,  49.723, 456.781, -72.18]
nn = [str(X) for X in numbers]

for i in range(len(nn)):
    numstring = "{value[0]:>6}.{value[1]:<6}"
    print numstring.format(value=nn[i].split('.') if '.' in nn[i] else (nn[i], '0'))

然后我们可以将小数点处的字符串拆分为整数和小数部分。如果缺少小数部分,我们将其分配给0

注意:使用此解决方案时,需要在格式化操作之前将数字转换为字符串。

这是输出:

  4.8
 49.723 
456.781 
-72.18  
编辑:我认为FeebleOldMan的solution比我的好,你应该选择它。

答案 4 :(得分:1)

使用Python文档中的配方:prependTo()

from decimal import Decimal


def moneyfmt(value, places=3, curr='', sep=',', dp='.',
             pos='', neg='-', trailneg=''):
    [...]

numbers = [4.8, 49.723, 456.781, -72.18]
for x in numbers:
    value = moneyfmt(Decimal(x), places=2, pos=" ")
    print("{0:>10s}".format(value))

你将获得:

  4.800
 49.723
456.781
-72.180

答案 5 :(得分:1)

这是我的方法!

default_args = {
    'owner': config.OWNER,
    'depends_on_past': False,
    'start_date': datetime(2018, 10, 14, 22, 0, 0),
    'email': [config.ALERT_EMAIL],
    'email_on_failure': True,
    'email_on_retry': False,
    'retry_delay': timedelta(minutes=1),
    'retries': 2,
}

# DAG
dag = DAG('Test',
          default_args=default_args,
          description='Initial setup',
          schedule_interval='@daily')

我喜欢其他解决方案,但需要一些特定的东西,并考虑为什么不共享!

答案 6 :(得分:1)

如果您不介意尾随零,那么简单的方法是:

numbers = [4.8,49.723,456.781,-72.18,5,13]
for f in numbers:
    print('{:>7.3f}'.format(f))

哪些印刷品:

   4.800
  49.723
 456.781
 -72.180
   5.000
  13.000

如果要摆脱尾随的零,可以做的一件事是使用正则表达式模块中的re.sub方法:

import re

numbers = [4.8,49.723,456.781,-72.18,5,13]
for f in numbers:
    print(re.sub(r'\.?0+$','','{:>7.3f}'.format(f)))

哪些印刷品:

  4.8
 49.723
456.781
-72.18
  5
 13

但是,这将为您提供不同宽度的列。唯一的区别是空格,因此您看不到它,但是如果您将它作为表的一部分来做,它将看起来像这样:

import re

numbers = [4.8,49.723,456.781,-72.18,5,13]
for f in numbers:
    print(re.sub(r'\.?0+$','','{:>7.3f}'.format(f)),'|')

打印:

  4.8 |
 49.723 |
456.781 |
-72.18 |
  5 |
 13 |

为避免这种情况,如果您想真正地 可以这样做:

import re

numbers = [4.8,49.723,456.781,-72.18,5,13]
for f in numbers:
    print(re.sub(r'\.?0+$',lambda match: ' '*(match.end()-match.start()),'{:>7.3f}'.format(f)),'|')

哪些印刷品:

  4.8   |
 49.723 |
456.781 |
-72.18  |
  5     |
 13     |

希望这会有所帮助!

答案 7 :(得分:0)

您可以使用Python [decimal][1]类型。

有一个recipe用来格式化货币价值。

为什么decimal键入:避免舍入问题,正确处理有意义的数字......

答案 8 :(得分:0)

我迟到了,但是您也可以使用数学,特别是对数的属性来计算出将所有数字填充到正确的小数位所需的空格量。

from math import log10

nums = [4.8, 49.723, 456.781, -72.18, 5, 13]

def pre_spaces(nums):
    absmax = max([abs(max(nums)), abs(min(nums))])
    max_predot = int(log10(absmax))
    spaces = [' '*(max_predot-int(log10(abs(num))) - (1 if num<0 else 0)) for num in nums]
    return spaces

for s,n in zip(pre_spaces(nums), nums):
    print('{}{}'.format(s,n))

结果是:

  4.8
 49.723
456.781
-72.18
  5
 13

答案 9 :(得分:0)

是的,可以使用许多直接方法来对齐小数点附近的浮点数。下面给出的2行代码是一个示例

`在[20]中:floating =([。022,12.645,544.5645,.54646,-554.56,-。2215,-546.5446])

在[21]中:对于浮动的xxx:打印“ {0:10.4f}”。format(xxx) `

{0:10.4f}中的0是每个浮点项的尺寸。冒号后面的空格是可选的负号。 10是十进制前的位数,4是十进制后的位数。 这是我作为JPG result

输出的

答案 10 :(得分:0)

大多数答案首先创建一个字符串,然后将其拆分为小数以进行进一步操作。也可以使用 divmod 将数字拆分为整数部分和小数部分。解决方案可能如下所示:

for x in [4.8, 49.723, 456.781, -72.18,  5, 13]:

    print('[{:s}{}{:4s}]'.format('{:6.0f}'.format(x//1),
                                 '.' if x%1 else ' ',
                                 '{:0.4f}'.format(x%1).strip('.0')))

产生:

[     4.8   ]
[    49.723 ]
[   456.781 ]
[   -73.82  ]
[     5     ]
[    13     ]

如果您可以容忍尾随小数,您可以通过在中间删除 if/else 部分来进一步简化。