Печать переменной с плавающей точкой с точностью, заданной другой переменной - PullRequest
0 голосов
/ 25 июня 2019

Используя python, я хотел бы вывести значения двух переменных (с плавающей точкой).Точность, с которой две переменные будут напечатаны, должна зависеть от самих значений переменных.На самом деле, я буду печатать значение и соответствующую ошибку.Я не знаю заранее, сколько соответствующих цифр «Значение» и «Ошибка» будет иметь.

Ниже приведены несколько примеров:

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(Value is {???} and error is {:.1g}).format(value, error)

У вас есть предложения?Я уверен, что решение довольно простое, но я не могу его найти.

Ответы [ 2 ]

2 голосов
/ 25 июня 2019

Это намного проще, если вы используете строку форматирования, потому что вы можете заменить даже параметры форматирования в ней.Это позволит вам управлять всеми атрибутами программно:

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. Другими словами, округлениезначение, равное половине величины ошибки round(2*N,p)/2 для учета округления, примененного к диапазону значений.

0 голосов
/ 25 июня 2019

Я думаю, что мы могли бы как-то использовать пакет decimal для достижения этой цели. Я играл с этим и придумал следующее решение. Это довольно многословно по сравнению с решением , предложенным Аленом, но, вероятно, может быть улучшено:

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
...