Форум сайта python.su
загружаю числовые данные с сервера, и часть из них в формате 1е-8, что-бы не было лишнего дерьма вроде 1.0000000000000000209225608301284726753266340892878361046314239501953125e-8 сразу преобразую в str а затем в Decimal (прилетает float или int и поэтому такой костыль) , так как нужны точные расчеты , необходимо избавиться от отображения с экспонентой и прийти к виду 0.00000001 , это надо для отображения пользователю (строковый формат), как это сделать ?
гугл молчит а форматирование строк (единственное что было в гугле) не подходит так как там требуется точно указывать сколько знаков до и после запятой а у меня данные самые разношерстные
Офлайн
@cckyi_boxxxНапиши функцию, которая работает с числом как со строкой. Из строки 1e-8 можно извлечь каждую часть с помощью регулярного выражения и дальше каждую из них превратить в число. Потом эти числа можно использовать для добавления нулей. То есть для вычисления используешь некрасивые, но точные числа, а для показывания пользователям приводишь их к красивому виду.
необходимо избавиться от отображения с экспонентой и прийти к виду 0.00000001 , это надо для отображения пользователю (строковый формат), как это сделать ?
Отредактировано py.user.next (Июль 14, 2019 05:36:01)
Офлайн
прилетают разные числа, просто беспокоят меня только те из них которые с экспонентой, подобного рода костыль можно сделать и при помощи Decimal, он позволяет получить все части числа по отдельности, хотелось-бы без костылей
пробовал юзать локальный контекст модуля decimal
from decimal import * tsz = 1e-8 with localcontext( Context(prec = 32, rounding = ROUND_05UP , Emin = 0 , Emax = 0 , clamp=1 , capitals=0) ): tsz = Decimal(str(tsz) ) print(tsz)
Офлайн
@cckyi_boxxxЗачем?
пробовал запретить экспоненту
>>> '{:e}'.format(1) '1.000000e+00' >>> '{:e}'.format(123) '1.230000e+02' >>> '{:e}'.format(123.456) '1.234560e+02' >>> '{:e}'.format(0.00123456) '1.234560e-03' >>>
@cckyi_boxxxДа это обычное дело: когда хочешь пользователю вывести что-то определённое, ты делаешь для этого функцию. Не надо пытаться питон поднастроить, а тем более воздействовать на сами числа из-за их внешнего вида, меняя что-то в них самих.
если воспользоваться вашим советом то это получится довольно размашистый код
Офлайн
> сразу преобразую в str а затем в Decimal (прилетает float или int и поэтому такой костыль)
Просто округляй данные до заданной точности. Типом Decimal я никому не рекомендую пользоваться. http://python.su/forum/topic/35829/?page=1#post-194791
Офлайн
@cckyi_boxxxДумаю что нет лаконичного способа, просто потому что это никому не нужно. Если нужен Decimal то его и передают по сети, если приходит float то все нормальные люди понимают что 1.5 и 1.4999999999999 это одно и тоже. А любой разумный вывод как раз легко форматами настраивается, не зря алгоритмы форматирования при выводе уже десятки лет неизменны.
полагаю должен быть более лаконичный способ.
Офлайн
doza_andну по сети все летит json-ом и соответствующий модуль питона для работы с этим форматом переводит все числа с плавающей точкой во float, и возможно-ли этому модулю “обьяснить” что надо сразу в decimal я не знаю , поэтому поставил такой костыль и он работает.
Если нужен Decimal то его и передают по сети
Офлайн
@cckyi_boxxxjson как формат не поддерживает Decimal и у него не предусмотрены методы передачи доп информации о типе (в отличии например от yaml). Классическое решение при отправке преобразовать все Decimal в строки, а при получении отконвертировать их назад. При этом не будет потерь. Ну или использовать более подходящий протокол обмена.
по сети все летит json-ом
Офлайн
> насколько я понял описанная по ссылке проблема в том что параметр prec слишком мал для точных вычислений
Не совсем, проблема в том что стандартный тип Decimal работает не верно. Он не позволяет задать точность вычислений. Например если я захочу поделить 22 рубля между 7-ю людьми, то у меня получится Decimal('3.142857142857142857142857143') что при финансовых расчётах не допустимо. Но и задать нужную точность через prec так что бы он автоматически округлял дробную часть тоже не получится.
> в моем случае стоит 32 хотя максимум что имею это 20 символов дробной + целой части
Ну как бы:
>>> len("1.0000000000000000209225608301284726753266340892878361046314239501953125") 72
Офлайн
Rodegastокругление не спасет. так как на выходе тот-же float просто один мусор поменяется на другой или вовсе останется прежним как в приведенном ниже примере, + ошибки при математических операциях, я подумывал юзать numpy или pandas, у них свои типы и работают они точно, но в моем случае их не очень удобно использовать, возможно под питон есть что-то позволяющее работать точно как numpy но не с массивами а с переменными (кроме Decimal)?
Если важна точность, то надо её определить и округлять входные данные и результаты вычислений до этой точности.
tsz = 1e-8 with localcontext( Context(prec = 32, rounding = ROUND_05UP , Emin = 0 , Emax = 0 , clamp=1 , capitals=0) ): print(Decimal(tsz)) tsz = round(tsz, 8) print(Decimal(tsz)) >>> 1.0000000000000000209225608301284726753266340892878361046314239501953125e-8 1.0000000000000000209225608301284726753266340892878361046314239501953125e-8
Офлайн