Мне нужно округлить число с плавающей точкой для отображения в пользовательском интерфейсе. Например, на одну значимую цифру:
1234 -> 1000
0,12 -> 0,1
0,012 -> 0,01
0,062 -> 0,06
6253 -> 6000
1999 -> 2000
Есть ли хороший способ сделать это с помощью библиотеки Python, или я должен написать это сам?
Ответы:
Вы можете использовать отрицательные числа для округления целых чисел:
Таким образом, если вам нужна только самая значимая цифра:
Вам, вероятно, придется позаботиться о том, чтобы число с плавающей точкой стало целым, если оно больше 1.
источник
log10
- единственный правильный способ определить, как его округлить.log10(abs(x))
, в противном случае отрицательные числа потерпят неудачу (И,x == 0
конечно, относиться к ним отдельно)round_to_n = lambda x, n: x if x == 0 else round(x, -int(math.floor(math.log10(abs(x)))) + (n - 1))
защищает отx==0
иx<0
Спасибо @RoyHyunjinHan и @TobiasKienzler. Не защищен от неопределенного , как math.inf, или мусор , как никто и т.д.% g в форматировании строки будет форматировать число с плавающей точкой, округленное до некоторого числа значащих цифр. Иногда он использует научную нотацию 'e', поэтому преобразуйте округленную строку обратно в число с плавающей точкой, а затем через форматирование строки% s.
источник
0.075
до0.08
. Это возвращается0.07
вместо.round_sig = lambda f,p: float(('%.' + str(p) + 'e') % f)
позволяет настроить количество значащих цифр!Если вы хотите иметь значение, отличное от 1 значащей десятичной дроби (в остальном такое же, как у Евгения):
источник
0.075
до0.08
. Это возвращается0.07
вместо.round
. docs.python.org/2/tutorial/floatingpoint.html#tut-fp-issuesЭто решение отличается от всех остальных тем, что:
Для произвольного числа
n
значащих цифр вы можете использовать:Тест:
Примечание : с этим решением невозможно динамически адаптировать количество значащих цифр от входных данных, потому что не существует стандартного способа различать числа с разными числами конечных нулей (
3.14 == 3.1400
). Если вам нужно сделать это, то вам нужны нестандартные функции, подобные тем, которые представлены в пакете to-precision .источник
:g
форматера, который сохраняет целые числа.2000.0
предлагает 5 значащих цифр, поэтому он должен пройти{:g}
снова.) В целом, целые числа с конечными нулями являются неоднозначными в отношении значащих цифр, если только не используется какой-либо метод (например, подчеркивание над последним значащим).Я создал пакет с высокой точностью, который делает то, что вы хотите. Это позволяет вам давать своим цифрам более или менее значимые цифры.
Он также выводит стандартную, научную и инженерную нотацию с указанным количеством значащих цифр.
В принятом ответе есть строка
Это на самом деле определяет 8 сиг фиг. Для числа 1234243 моя библиотека отображает только одну значимую цифру:
Он также округляет последнюю значащую цифру и может автоматически выбирать, какую нотацию использовать, если нотация не указана:
источник
lambda x: to_precision(x, 2)
Чтобы округлить целое число до 1 значащей цифры, основная идея состоит в том, чтобы преобразовать ее в число с плавающей запятой с 1 цифрой перед точкой и округлить ее, а затем преобразовать обратно в исходный целочисленный размер.
Для этого нам нужно знать наибольшую степень на 10 меньше, чем целое число. Для этого мы можем использовать пол функции log 10.
источник
Чтобы прямо ответить на вопрос, вот моя версия с использованием именования из функции R :
Моей главной причиной для публикации этого ответа являются комментарии с жалобами на то, что «0,075» округляется до 0,07, а не 0,08. Это связано с тем, что «Новичок С» указывает на комбинацию арифметики с плавающей запятой, имеющей как конечную точность, так и представление с основанием-2 . Ближайшее к 0,075 число, которое действительно может быть представлено, немного меньше, поэтому округление получается не так, как вы могли наивно ожидать.
Также обратите внимание, что это относится к любому использованию недесятичной арифметики с плавающей запятой, например, C и Java имеют одинаковую проблему.
Чтобы показать более подробно, мы просим Python отформатировать число в шестнадцатеричном формате:
который дает нам:
0x1.3333333333333p-4
. Причина этого заключается в том, что нормальное десятичное представление часто включает в себя округление и, следовательно, не то, как компьютер фактически «видит» число. Если вы не привыкли к этому формату, пара полезных ссылок - это документы по Python и стандарт Си .Чтобы показать, как эти числа работают немного, мы можем вернуться к нашей отправной точке, выполнив:
который должен распечатать
0.075
.16**13
это потому, что после десятичной запятой есть 13 шестнадцатеричных цифр, и2**-4
потому, что шестнадцатеричные показатели являются base-2.Теперь у нас есть некоторое представление о том, как представлены числа с плавающей точкой, и мы можем использовать
decimal
модуль для большей точности, показывая нам, что происходит:давать:
0.07499999999999999722444243844
и, надеюсь, объяснить, почемуround(0.075, 2)
оценивает0.07
источник
0.074999999999999999
, то , что вы ожидаете получить в этом случае?Надеюсь, что мы взяли лучшие из всех ответов, приведенных выше (минус возможность поставить его как одну строку лямбда;)). Еще не изучен, не стесняйтесь редактировать этот ответ:
источник
Я изменил решение Indgar для обработки отрицательных чисел и небольших чисел (включая ноль).
источник
x == 0
? Если вы любите однострочник, простоreturn 0 if x==0 else round(...)
.0.970 == 0.97
). Я думаю, что вы могли бы использовать некоторые другие решения для печати, например,f'{round_sig(0.9701, sig=3):0.3f}'
если вы хотите печатать ноль.Если вы хотите округлить без использования строк, ссылка, которую я нашел, похоронена в комментариях выше:
http://code.activestate.com/lists/python-tutor/70739/
мне кажется лучшим Затем, когда вы печатаете с любыми дескрипторами форматирования строки, вы получаете разумный вывод и можете использовать числовое представление для других целей расчета.
Код по ссылке состоит из трех строк: def, doc и return. В нем есть ошибка: вам нужно проверить наличие логарифмов. Это просто. Сравните вход с
sys.float_info.min
. Полное решение:Это работает для любого скалярного числового значения, и n может быть a,
float
если вам нужно сместить ответ по какой-то причине. Вы можете увеличить предел:без провокации ошибки, если по какой-то причине вы работаете с минимальными значениями.
источник
Я не могу придумать ничего такого, что могло бы справиться с этим из коробки. Но это довольно хорошо обрабатывается для чисел с плавающей запятой.
Целые числа сложнее. Они не хранятся в памяти как база 10, поэтому значимые места не являются естественным делом. Это довольно тривиально реализовать, когда они являются строкой.
Или для целых чисел:
Если вы хотите создать функцию, которая обрабатывает любое число, я бы предпочел преобразовать их в строки и найти десятичное место, чтобы решить, что делать:
Другой вариант - проверить тип. Это будет гораздо менее гибко, и, вероятно, не будет хорошо играть с другими числами, такими как
Decimal
объекты:источник
Размещенный ответ был наилучшим из имеющихся, когда он был дан, но он имеет ряд ограничений и не дает технически правильных значимых цифр.
numpy.format_float_positional напрямую поддерживает желаемое поведение. Следующий фрагмент возвращает число с плавающей запятой,
x
отформатированное до 4 значащих цифр, с подавленной научной нотацией.источник
print(*[''.join([np.format_float_positional(.01*a*n,precision=2,unique=False,fractional=False,trim='k',pad_right=5) for a in [.99, .999, 1.001]]) for n in [8,9,10,11,12,19,20,21]],sep='\n')
. Я не проверял сам Dragon4.Я тоже столкнулся с этим, но мне нужно было контролировать тип округления. Таким образом, я написал быструю функцию (см. Код ниже), которая может принимать во внимание значение, тип округления и требуемые значащие цифры.
источник
Использование форматирования в новом стиле Python 2.6+ (так как стиль% не рекомендуется):
В Python 2.7+ вы можете опустить ведущие
0
s.источник
Эта функция выполняет нормальное округление, если число больше 10 ** (- decimal_positions), в противном случае добавляет больше десятичного числа, пока не будет достигнуто количество значащих десятичных позиций:
Надеюсь, поможет.
источник
https://stackoverflow.com/users/1391441/gabriel , отвечает ли следующее ваше беспокойство по поводу rnd (.075, 1)? Предупреждение: возвращает значение в виде числа с плавающей запятой
источник
Это возвращает строку, так что результаты без дробных частей и небольшие значения, которые в противном случае появлялись бы в нотации E, отображаются правильно:
источник
На такой вопрос так тщательно ответили, почему бы не добавить еще один
Это подходит моей эстетике немного лучше, хотя многие из вышеперечисленных сопоставимы
Это работает для отдельных чисел и числовых массивов и должно нормально работать для отрицательных чисел.
Есть еще один шаг, который мы могли бы добавить - np.round () возвращает десятичное число, даже если округлено целое число (т. Е. Для значимых значений = 2 мы можем ожидать возврата -460, но вместо этого мы получим -460.0). Мы можем добавить этот шаг, чтобы исправить это:
К сожалению, этот последний шаг не будет работать для массива чисел - я оставлю это вам, дорогой читатель, чтобы выяснить, если вам нужно.
источник
Sigfig пакет / библиотека охватывает это. После установки вы можете сделать следующее:
источник
источник