在Python中,我需要格式化数字,使它们在小数点上对齐,如下所示:
4.8
49.723
456.781
-72.18
5
13
有没有一种直截了当的方法来做到这一点?
答案 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)
答案 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)
大多数答案首先创建一个字符串,然后将其拆分为小数以进行进一步操作。也可以使用 div
和 mod
将数字拆分为整数部分和小数部分。解决方案可能如下所示:
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 部分来进一步简化。