Найти - Пользователи
Полная версия: как избавится от экспоненты в переменной Decimal
Начало » Python для новичков » как избавится от экспоненты в переменной Decimal
1 2
@cckyi_boxxx
загружаю числовые данные с сервера, и часть из них в формате 1е-8, что-бы не было лишнего дерьма вроде 1.0000000000000000209225608301284726753266340892878361046314239501953125e-8 сразу преобразую в str а затем в Decimal (прилетает float или int и поэтому такой костыль) , так как нужны точные расчеты , необходимо избавиться от отображения с экспонентой и прийти к виду 0.00000001 , это надо для отображения пользователю (строковый формат), как это сделать ?

гугл молчит а форматирование строк (единственное что было в гугле) не подходит так как там требуется точно указывать сколько знаков до и после запятой а у меня данные самые разношерстные
py.user.next
@cckyi_boxxx
необходимо избавиться от отображения с экспонентой и прийти к виду 0.00000001 , это надо для отображения пользователю (строковый формат), как это сделать ?
Напиши функцию, которая работает с числом как со строкой. Из строки 1e-8 можно извлечь каждую часть с помощью регулярного выражения и дальше каждую из них превратить в число. Потом эти числа можно использовать для добавления нулей. То есть для вычисления используешь некрасивые, но точные числа, а для показывания пользователям приводишь их к красивому виду.
@cckyi_boxxx
прилетают разные числа, просто беспокоят меня только те из них которые с экспонентой, подобного рода костыль можно сделать и при помощи 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)
здесь параметрами Emin = 0 , Emax = 0 пробовал запретить экспоненту, но какими-бы я их не выставлял результат одинаков, экспонента не убирается, если воспользоваться вашим советом то это получится довольно размашистый код, сначала определить есть экспонента или нет, затем разложить число, затем собрать строку по инструкции, полагаю должен быть более лаконичный способ.
py.user.next
@cckyi_boxxx
пробовал запретить экспоненту
Зачем?

У всех чисел есть экспонента, хоть они целые, хоть не целые.

1 = 1e+0 = 1e-0
123 = 1.23e+2
123.456 = 1.23456e+2
0.00123456 = 1.23456e-3

  
>>> '{: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
если воспользоваться вашим советом то это получится довольно размашистый код
Да это обычное дело: когда хочешь пользователю вывести что-то определённое, ты делаешь для этого функцию. Не надо пытаться питон поднастроить, а тем более воздействовать на сами числа из-за их внешнего вида, меняя что-то в них самих.
Rodegast
> сразу преобразую в str а затем в Decimal (прилетает float или int и поэтому такой костыль)

Просто округляй данные до заданной точности. Типом Decimal я никому не рекомендую пользоваться. http://python.su/forum/topic/35829/?page=1#post-194791
doza_and
@cckyi_boxxx
полагаю должен быть более лаконичный способ.
Думаю что нет лаконичного способа, просто потому что это никому не нужно. Если нужен Decimal то его и передают по сети, если приходит float то все нормальные люди понимают что 1.5 и 1.4999999999999 это одно и тоже. А любой разумный вывод как раз легко форматами настраивается, не зря алгоритмы форматирования при выводе уже десятки лет неизменны.
@cckyi_boxxx
doza_and
Если нужен Decimal то его и передают по сети
ну по сети все летит json-ом и соответствующий модуль питона для работы с этим форматом переводит все числа с плавающей точкой во float, и возможно-ли этому модулю “обьяснить” что надо сразу в decimal я не знаю , поэтому поставил такой костыль и он работает.

Что до методов форматирования мою задачу ими не решить так как нужно единое решение для целых, дробных без экспоненты и дробных с экспонентой чисел, и без лишних нулей для нормального восприятия. Или я хуже вас разбираюсь в методах форматирования, что весьма вероятно.

Rodegast, спасибо за предупреждение, насколько я понял описанная по ссылке проблема в том что параметр prec слишком мал для точных вычислений, в моем случае стоит 32 хотя максимум что имею это 20 символов дробной + целой части, тут гораздо важнее точность вычислений и другого более подходящего модуля я не нашел.

doza_and
@cckyi_boxxx
по сети все летит json-ом
json как формат не поддерживает Decimal и у него не предусмотрены методы передачи доп информации о типе (в отличии например от yaml). Классическое решение при отправке преобразовать все Decimal в строки, а при получении отконвертировать их назад. При этом не будет потерь. Ну или использовать более подходящий протокол обмена.
Rodegast
> насколько я понял описанная по ссылке проблема в том что параметр prec слишком мал для точных вычислений

Не совсем, проблема в том что стандартный тип Decimal работает не верно. Он не позволяет задать точность вычислений. Например если я захочу поделить 22 рубля между 7-ю людьми, то у меня получится Decimal('3.142857142857142857142857143') что при финансовых расчётах не допустимо. Но и задать нужную точность через prec так что бы он автоматически округлял дробную часть тоже не получится.

> в моем случае стоит 32 хотя максимум что имею это 20 символов дробной + целой части

Ну как бы:
 >>> len("1.0000000000000000209225608301284726753266340892878361046314239501953125")
72

> тут гораздо важнее точность вычислений и другого более подходящего модуля я не нашел.

Если важна точность, то надо её определить и округлять входные данные и результаты вычислений до этой точности.
@cckyi_boxxx
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
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB