浮動小数点数の小数点以下の桁を見つける簡単な方法または統合された機能はありますか?
数値は文字列から解析されるため、1つの方法は「。」の後の数字をカウントすることです署名しますが、それは私には非常に不格好に見えます。 float
またはDecimal
オブジェクトから必要な情報を取得する可能性はありますか?
[〜#〜] solution [〜#〜](もちろん、そのうちの1つ:))
私は問題を解決するためにpython decimal.Decimalクラスを使用することを選択しました:
e = abs(Decimal(string_value).as_Tuple().exponent)
注:これは、Decimalの構築元のパラメーターが浮動小数点ではなく文字列である場合にのみ機能します(浮動小数点の不正確さを引き起こす)。
他のすべての貢献に感謝します。
他の人が言ったことを繰り返すために(すでに入力しているからです!)、浮動小数点数の場合、10進表現と2進表現の違いのために、そのような値が意味があるかどうかもわかりません。多くの場合、有限数の10進数で表現できる数値は、2進数の無限桁の表現しかありません。
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
より大きい場合を除き、小数点以下の桁数です。
素朴な方法(@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])
「小数点以下の桁数」は、内部的に格納および処理される方法のため、浮動小数点数が持つプロパティではありません。
浮動小数点数から好きなだけ小数点以下の桁を取得できます。問題は、どの程度の精度が必要かです。浮動小数点数を文字列に変換するとき、プロセスの一部は精度を決定します。
例えば試してみてください:
1.1 - int(1.1)
そして、答えは次のようになります。
0.10000000000000009
したがって、この場合、小数の数は17です。これは、おそらく探している数ではありません。
ただし、「round」を使用して、数値を特定の小数に丸めることができます。
round(3.1415 - int(3.1415), 3)
この場合、小数の数は3に削減されます。
「フロートから小数点以下の桁数」を取得することはできませんが、精度と必要な数を決定することはできます。
フロートを文字列に変換することは、このような決定を行う1つの方法です。
10進数ライブラリは、会計などのように10進数を扱うためのものです。本質的に、小数点以下の桁数を返す機能はありません。これは、実行されるコンテキストがユーザーが望むものに設定することに気づいた場合に特に問題になります。
文字列を取得する場合、10進数に変換できますが、これはゼロに固定して正確性を高めるか、丸め設定を使用して切り捨てます。
最善の方法は、おそらく文字列のドットで分割し、結果の部分文字列の文字数を数えることです。
解析の問題が発生しないことがわかっている場合(またはpython自体または他のライブラリがそれを処理し、ローカリゼーションの問題を処理することを希望している場合)... modf を使用します。戻り値は値のペアで、一方は整数部、もう一方は小数部です。
私はこのようなものが必要であり、これらのいくつかをテストしました、私が見つけた最速は:
str(number)[::-1].find('.')
浮動小数点の問題のため、すべてのモジュロのものは、Decimal(number)でも間違った結果を与えました(db全体の価格を修正するスクリプトでこれが必要だったことに注意してください)
len(str(Decimal(str(number))) % Decimal(1))) - 2
文字列をDecimalに入れる必要性は、フロートなどの場合には非常に不安です。
これが私の「ベンチ」です。 https://repl.it/FM8m/17
小数点の後の計算数字と数字の丸めで私が見つけた最速の方法は
数字を計算する:
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
Python浮動小数点数は、10進数ではなく2進数として内部的に表されるため、10進数に変換する以外にショートカットはありません。組み込みの唯一の方法は、文字列に変換することです。 10進変換を実行して数字をカウントする独自のコードを作成できますが、これは労力の重複になります。