打印精度由另一个变量设置的float变量

时间:2019-06-25 13:31:11

标签: python rounding string-formatting precision

使用python,我想打印两个变量(浮点数)的值。打印两个变量的精度应取决于变量值本身。实际上,我将打印一个值和相关的错误。我事先不知道“ Value”和“ Error”将有多少个相关数字。

下面是一些示例:

Value: 15236.265, Error = 0.059 --> printed value 15236.27 +- 0.06
Value: 15236.265, Error = 3.738 --> printed value 15236 +- 4
Value: 15236.265, Error = 275.658 --> printed value 15200 +- 300

理想情况下,我想确定print语句中要使用的精度,如下所示。

print(Value is {???} and error is {:.1g}).format(value, error)

您有什么建议吗?我相信解决方案非常简单,但是我找不到。

2 个答案:

答案 0 :(得分:2)

如果使用格式字符串,这会容易得多,因为您甚至可以替换其中的格式参数。这将允许您以编程方式控制所有属性:

value = 15236.265
error = 3.738
p1    = 10
p2    = 3
print(f"Value is {value:.{p1}g} and error is {error:.{p2}g}")

# 'Value is 15236.265 and error is 3.74'

编辑

我从您的评论中看到,这不是格式问题,而是四舍五入问题。您想舍入错误的尾数,并将相同的舍入应用于值本身。

这是一个可以为您完成的功能:

from math import log
def roundError(N,E):
    p=-round(log(E,10)-0.5)
    return round(N,p),round(E,p)

roundError(15236.265,0.059)   # --> (15236.26, 0.06)
roundError(15236.265,3.738)   # --> (15236, 4)
roundError(15236.265,275.658) # --> (15200, 300)  

然后您可以打印这些数字而无需任何特殊格式。

您可能不必担心,但我想指出的是,此值/误差调整将在误差范围内稍微抵消可能值的范围。

例如:

15236.265 +/- 275.658 ==> 14960.607 ... 15511.923
15200     +/- 300     ==> 14900     ... 15500  (extra 60 low and missing 12 high)

要谨慎行事,可能需要将取整的值范围应为14950 ... 15550,即15250 +/-300。换句话说,将值取整为误差{{1}的一半。 }来说明应用于该值范围的舍入。

答案 1 :(得分:0)

我认为我们可以以某种方式使用decimal软件包来实现这一目标。我正在研究它,并提出了以下解决方案。与Alain给出的solution相比,它很冗长,但可能需要进一步改进:

from decimal import Decimal


def error_format(value: float, 
                 error: float, 
                 significant_digits: int = 1):
    def remove_exponent(d):
        return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()

    value = Decimal(str(value))
    error = Decimal(str(error))
    error_exp = error.logb()
    ndigits = -int(error_exp) + significant_digits - 1
    rounded_value = round(value, ndigits)
    rounded_error = round(error, ndigits)
    return remove_exponent(rounded_value), remove_exponent(rounded_error)

以及用法示例:

values = [15236.265] * 3
errors = [0.059, 3.738, 275.658]

for value, error in zip(values, errors):
    print('Value is {} and error is {}'.format(*error_format(value, error)))

for value, error in zip(values, errors):
    print('Value is {} and error is {}'.format(*error_format(value, error, significant_digits=3)))

给予:

Value is 15236.26 and error is 0.06
Value is 15236 and error is 4
Value is 15200 and error is 300
Value is 15236.265 and error is 0.059
Value is 15236.26 and error is 3.74
Value is 15236 and error is 276