我不在乎小数点的位置,并且希望在适当的情况下以科学的符号进行打印以最大程度地显示。但是,我想适当地四舍五入以保持固定的宽度,向左破烂或向右破烂都可以。
例如
>>> my_format("{:10f}", 0.0000000456)
" 4.56e-08"
>>> my_format("{:10f}", 12.345678987654321)
" 12.345679"
#or "12.34567890" because significant digits
#but not "1.2346e+01", since it is less accurate than the above representations
>>> my_format("{:10f}", 12345678987654321)
"1.2345e+16"
编辑以澄清示例,width
格式说明符未提供固定宽度。它提供了最小宽度。如何获得固定宽度的表示形式?
答案 0 :(得分:3)
g
格式说明符通常是不错的选择,如果您想使用科学记数法,即:
my_format = "{:.10g}".format
应该做正确的事情:
>>> list(my_format(v) for v in (0.0000000456, 12.345678987654321, 12345678987654321))
['4.56e-08', '12.34567899', '1.234567899e+16']
后来我意识到上述功能不能满足OP的要求
基于@a_guest的有用评论,我提出了以下建议:
def my_format(v, length=10):
n = length
while n > 0:
i = len('%#.*g' % (n, v))
s = '%.*g' % (n + n - i, v)
if len(s) <= length:
return s
n -= 1
return s
现在我得到['4.56e-08', '12.345679', '1.2346e+16']
了,它更接近想要的东西。
我已经使用以下方法生成了大量随机数进行了测试:
from random import uniform
def rnd_float():
return uniform(-10, 10) * 10 ** (uniform(-1.6, 1.6) ** 11)
相当随意,但是生成的数字与我所关心的分布相当接近。即大多在1附近,但有些很小或很大,几率还不错。
我已将数字从此传递给my_format
10万次,然后又获得了格式正确的数字。
答案 1 :(得分:1)
您需要的是一种保持显示的字符数的方法。因此,创建一个函数来做到这一点。
import decimal
# create a new context for this task
ctx = decimal.Context()
# 20 digits should be enough for everyone :D
ctx.prec = 20
def float_to_str(f):
"""
Convert the given float to a string,
without resorting to scientific notation
"""
d1 = ctx.create_decimal(repr(f))
return format(d1, 'f')
print float_to_str(0.0000000456)
print float_to_str(12.345678987654321)
答案 2 :(得分:1)
您可以测试将数字设置为{:f}
和{:e}
的格式,然后解析生成的字符串以查看哪个更合适:
import re
def format(spec, number):
def _decimal(s):
return re.search(r'^\s*-?([0-9]+(\.[0-9]+)?)', s).group(1)
def _significant_digits(s):
return _decimal(s).rstrip('0')
def _fit_to_width(s):
decimal, significant = _decimal(s), _significant_digits(s)
stripped = s.replace(decimal, significant)
excess = len(stripped) - spec
if excess > 0:
# Replace excess digits from the right.
significant = significant[::-1].replace(
re.match(
r'[0-9]{{,{}}}'.format(excess),
significant[::-1]
).group(0), ''
)[::-1]
return s.replace(decimal, significant)
formats = [
_fit_to_width('{{:{}f}}'.format(spec).format(number)),
_fit_to_width('{{:{}e}}'.format(spec).format(number)),
]
return max(
filter(
lambda x: len(x[0]) <= spec,
[(f, len(_significant_digits(f))) for f in formats]
),
key=lambda x: x[-1]
)[0].rjust(spec)
print(format(10, 0.0000000456))
print(format(10, 12.345678987654321))
print(format(10, 12345678987654321))
# 4.56e-08
# 12.345679
# 1.2345e+16
答案 3 :(得分:0)
这似乎有效。可以摆脱numpy
,但是四舍五入需要更多的工作。
import numpy as np
SCIENTIFIC_NOTATION_WIDTH = 4
def my_format(number, n):
places = np.log10(np.abs(number))
if abs(places) == np.inf:
places = 0
highest_place = -int(places)
if 1 <= highest_place < 3:
rounded = np.round(number, n - highest_place - 1)
elif highest_place >= 3:
rounded = np.round(number, highest_place + n - 5)
elif -n < highest_place < 1:
rounded = np.round(number, n + highest_place - 2)
else:
rounded = np.round(number, highest_place + n - 6)
return "{{:{}.{}g}}".format(n,n).format(rounded)
print(my_format(12345678987654321, 10))
print(my_format(12.345678987654321,10))
print(my_format(0.0000000456,10))
#1.2346e+16
# 12.345679
# 4.56e-08
答案 4 :(得分:0)
如果提供的长度对于给定的数字来说太小,例如,下面的代码可以完成该工作并产生更长的输出。只能使用四个字符表示def rolling_window( aMatrix, aRollingWindowLENGTH ): # # http://www.rigtorp.se/2011/01/01/rolling-statistics-numpy.html
""" __doc__
USAGE: rolling_window( aMatrix, aRollingWindowLENGTH )
PARAMS: aMatrix a numpy array
aRollingWindowLENGTH a LENGTH of a Rolling Window
RETURNS: a stride_trick'ed numpy array with rolling windows
THROWS: n/a
EXAMPLE: >>> x = np.arange( 10 ).reshape( ( 2, 5 ) )
>>> rolling_window( x, 3 )
array([[[0, 1, 2], [1, 2, 3], [2, 3, 4]],
[[5, 6, 7], [6, 7, 8], [7, 8, 9]]])
>>> np.mean( rolling_window( x, 3 ), -1 )
array([[ 1., 2., 3.],
[ 6., 7., 8.]])
"""
new_shape = aMatrix.shape[:-1] + ( aMatrix.shape[-1] - aRollingWindowLENGTH + 1, aRollingWindowLENGTH )
new_strides = aMatrix.strides + ( aMatrix.strides[-1], )
return np.lib.stride_tricks.as_strided( aMatrix,
shape = new_shape,
strides = new_strides
)
。
4e100
产生
import math
def float_fmt(x, length=10):
reduce_fp_by = 0
if abs(x) > 0.0:
abs_power = abs(math.floor(math.log10(abs(x))))
if abs_power > 0:
power_len = max(1, math.floor(math.log10(abs_power)))
if abs_power > 4:
reduce_fp_by = power_len + 3
fp_n = max(0, length - reduce_fp_by - 1)
fmt = ('%#.'+str(fp_n)+'g')
return fmt % x
for l in [6, 8, 10, 13]:
for bf in [0, 4.2, 4.222, 4.22222, 4.2222222]:
for p in [-500, -100, -50, -5, 50, 100]:
f = bf * (10.0 ** p)
print(float_fmt(f, l), len(float_fmt(f, l)))