web-dev-qa-db-ja.com

小数位を見つける簡単な方法

浮動小数点数の小数点以下の桁を見つける簡単な方法または統合された機能はありますか?

数値は文字列から解析されるため、1つの方法は「。」の後の数字をカウントすることです署名しますが、それは私には非常に不格好に見えます。 floatまたはDecimalオブジェクトから必要な情報を取得する可能性はありますか?

[〜#〜] solution [〜#〜](もちろん、そのうちの1つ:))

私は問題を解決するためにpython decimal.Decimalクラスを使用することを選択しました:

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

注:これは、Decimalの構築元のパラメーターが浮動小数点ではなく文字列である場合にのみ機能します(浮動小数点の不正確さを引き起こす)。

他のすべての貢献に感謝します。

42
Constantinius

他の人が言ったことを繰り返すために(すでに入力しているからです!)、浮動小数点数の場合、10進表現と2進表現の違いのために、そのような値が意味があるかどうかもわかりません。多くの場合、有限数の10進数で表現できる数値は、2進数の無限桁の表現しかありません。

decimal.Decimalオブジェクトの場合、as_Tupleメソッドを使用して指数を取得できます。このメソッドは、signdigits、およびexponent属性:

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

指数の否定は、指数が0より大きい場合を除き、小数点以下の桁数です。

47
senderle

素朴な方法(@jglouieが言及するローカライズされた使用法に対して脆弱)は

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

ここで、fooは「23.512999238」のような文字列です。

編集

@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])
12
Mike Pennington

「小数点以下の桁数」は、内部的に格納および処理される方法のため、浮動小数点数が持つプロパティではありません。

浮動小数点数から好きなだけ小数点以下の桁を取得できます。問題は、どの程度の精度が必要かです。浮動小数点数を文字列に変換するとき、プロセスの一部は精度を決定します。

例えば試してみてください:

1.1 - int(1.1)

そして、答えは次のようになります。

0.10000000000000009

したがって、この場合、小数の数は17です。これは、おそらく探している数ではありません。

ただし、「round」を使用して、数値を特定の小数に丸めることができます。

round(3.1415 - int(3.1415), 3)

この場合、小数の数は3に削減されます。

「フロートから小数点以下の桁数」を取得することはできませんが、精度と必要な数を決定することはできます。

フロートを文字列に変換することは、このような決定を行う1つの方法です。

10
Alexander

10進数ライブラリは、会計などのように10進数を扱うためのものです。本質的に、小数点以下の桁数を返す機能はありません。これは、実行されるコンテキストがユーザーが望むものに設定することに気づいた場合に特に問題になります。

文字列を取得する場合、10進数に変換できますが、これはゼロに固定して正確性を高めるか、丸め設定を使用して切り捨てます。

最善の方法は、おそらく文字列のドットで分割し、結果の部分文字列の文字数を数えることです。

4
Spencer Rathbun

解析の問題が発生しないことがわかっている場合(またはpython自体または他のライブラリがそれを処理し、ローカリゼーションの問題を処理することを希望している場合)... modf を使用します。戻り値は値のペアで、一方は整数部、もう一方は小数部です。

1
jkerian

私はこのようなものが必要であり、これらのいくつかをテストしました、私が見つけた最速は:

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

浮動小数点の問題のため、すべてのモジュロのものは、Decimal(number)でも間違った結果を与えました(db全体の価格を修正するスクリプトでこれが必要だったことに注意してください)

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

文字列をDecimalに入れる必要性は、フロートなどの場合には非常に不安です。

これが私の「ベンチ」です。 https://repl.it/FM8m/17

1
Jérémy JOKE

小数点の後の計算数字と数字の丸めで私が見つけた最速の方法は

数字を計算する:

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
George

Python浮動小数点数は、10進数ではなく2進数として内部的に表されるため、10進数に変換する以外にショートカットはありません。組み込みの唯一の方法は、文字列に変換することです。 10進変換を実行して数字をカウントする独自のコードを作成できますが、これは労力の重複になります。

1
Mark Ransom