Простой способ найти десятичные разряды - PullRequest
40 голосов
/ 31 мая 2011

Существует ли простой способ или встроенная функция для определения десятичных разрядов числа с плавающей запятой?

Число разбирается из строки, поэтому одним из способов является подсчет цифр после '.'знак, но это выглядит довольно неуклюжим для меня.Есть ли возможность получить необходимую информацию из объекта float или Decimal?

РЕШЕНИЕ (один из них, конечно :))

Я решил использовать десятичный класс Python. Десятичный класс, чтобы помочь мне с моей проблемой:

e = abs(Decimal(string_value).as_tuple().exponent)

ПРИМЕЧАНИЕ: это работает только тогда, когда параметр, из которого строится десятичное число, является строкой, а не плавающей точкой (чтоприводит к неточностям с плавающей запятой).

Большое спасибо за все другие вклады.

Ответы [ 8 ]

47 голосов
/ 31 мая 2011

Чтобы повторить то, что сказали другие (потому что я уже напечатал это!), Я даже не уверен, что такое значение будет иметь смысл в случае числа с плавающей запятой, из-за разницы между десятичным и двоичнымпредставление;часто число, представимое конечным числом десятичных цифр, будет иметь только двоичное представление с бесконечной цифрой.

В случае объекта decimal.Decimal вы можете получить показатель степени с помощью метода as_tuple, который возвращает именованный кортеж с атрибутами sign, digits и exponent:

>>> d = decimal.Decimal('56.4325')
>>> d.as_tuple().exponent
-4
>>> d = decimal.Decimal('56.43256436')
>>> d.as_tuple().exponent
-8

Отрицание степени - это число цифр после десятичной точки, если только показатель степени не превышает 0.

10 голосов
/ 31 мая 2011

«число десятичных разрядов» не является свойством числа с плавающей запятой из-за того, как они хранятся и обрабатываются внутри.

Вы можете получить столько десятичных разрядов, сколько захотите, из числа с плавающей запятой. Вопрос в том, сколько точности вы хотите. При преобразовании числа с плавающей запятой в строку часть процесса определяет точность.

Попробуйте, например:

1.1 - int(1.1)

И вы увидите, что ответ:

0.10000000000000009

Итак, для этого случая число десятичных дробей равно 17. Вероятно, это не то число, которое вы ищете.

Однако вы можете округлить число до определенного количества десятичных знаков с помощью «round»:

round(3.1415 - int(3.1415), 3)

Для этого случая число десятичных дробей сокращается до 3.

Вы не можете получить «количество десятичных знаков от числа с плавающей запятой», но вы можете решить, какую точность и сколько вы хотите.

Преобразование числа с плавающей точкой в ​​строку является одним из способов принятия такого решения.

10 голосов
/ 31 мая 2011

Наивный способ (уязвимый для локального использования, упомянутого @jglouie) -

len(foo.split('.')[1])

где foo - строка типа "23.512999238".

EDIT

Как отметили @Thomas Jung и @Mark Ransom, это довольно наивно для некоторых угловых случаев, которые должны рассматриваться как ...

import re
from locale import localeconv
dec_pt = localeconv()['decimal_point']
decrgx = re.compile("\d+(%s\d+)?e(-|\+)(\d+)" % dec_pt)
if decrgx.search(foo):
    # still figuring this out
    raise NotImplementedError, "e notation not implemented"
else:
    digits = len(foo.split(dec_pt)[-1])
4 голосов
/ 31 мая 2011

Десятичная библиотека предназначена для работы с десятичными числами, как в Бухгалтерии. По своей сути он не имеет функции для возврата количества десятичных знаков. Это особенно проблема, когда вы понимаете, что контекст, в котором он работает, устанавливает его в соответствии с тем, что хочет пользователь.

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

Ваша лучшая ставка, вероятно, будет заключаться в разделении на точку в вашей строке и подсчете количества символов в результирующей подстроке.

1 голос
/ 27 апреля 2017

Самый быстрый способ, который я нашел для цифр вычисления после десятичной точки и округления числа:

Рассчитать цифры:

a=decimal.Decimal('56.9554362669143476');
lenstr = len(str(a).split(".")[1])

Расчет, проверка и округление:

a=decimal.Decimal('56.9554362669143476');
a = round(float(a),5) if len(str(a).split(".")[1]) > 5 else float(a)

Сравнение:

$ python2 -mtimeit 'import decimal; a=decimal.Decimal('56.9554362669143476'); round(float(a),5) if a.as_tuple().exponent < -5 else float(a)'
10000 loops, best of 3: 32.4 usec per loop
$ python -mtimeit 'import decimal; a=decimal.Decimal('56.9554362669143476'); a = round(float(a),5) if len(str(a).split(".")[1]) > 5 else float(a)'
100000 loops, best of 3: 16.7 usec per loop
1 голос
/ 18 января 2017

Мне нужно было что-то вроде этого, и я протестировал некоторые из них, самое быстрое, что я обнаружил:

str(number)[::-1].find('.')

Из-за проблемы с плавающей запятой все по модулю дали мне ложные результаты даже с десятичным числом (число) (обратите внимание, что мне нужно было это в скрипте, чтобы зафиксировать цены всего дБ)

len(str(Decimal(str(number))) % Decimal(1))) - 2

Необходимость поместить строку в десятичную систему довольно непросто, когда у нас есть числа с плавающей запятой или что-то вроде.

Вот моя "скамейка": https://repl.it/FM8m/17

1 голос
/ 31 мая 2011

Поскольку числа с плавающей запятой в Python внутренне представляются как двоичные, а не десятичные, на самом деле нет другого пути, кроме преобразования в десятичную.Единственный встроенный способ сделать это - преобразовать в строку.Вы можете написать свой собственный код для выполнения десятичного преобразования и подсчета цифр, но это будет дублированием усилий.

1 голос
/ 31 мая 2011

Если вы знаете, что у вас не возникнет проблем с синтаксическим анализом (или если вы разрешите самому Python или какой-либо другой библиотеке справиться с этим, надеюсь, с проблемами локализации) ... просто проанализируйте его и используйте modf . Возвращаемое значение представляет собой пару значений, одно из которых является неотъемлемой частью, а другое - дробной частью.

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