説明するまでもない理由で、len()で数えるためにfloatを文字列に変換する必要があるプログラムを作っています。しかし、str(float(x))では、文字列に変換したときにxが丸められてしまい、全体がおかしくなってしまいます。どなたか修正方法をご存知でしょうか? 知りたいなら使われているコードはこちら'。
len(str(float(x)/3))
浮動小数点数を扱う際には、何らかの形での丸めが避けられないことが多い。 これは、基数10で正確に表現できる数値が、コンピュータが使用する基数2で正確に表現できるとは限らないからです。
たとえば、次のような場合です。
>>> .1
0.10000000000000001
この場合、repr
を使って0.1を文字列に変換しています。
>>> repr(.1)
'0.10000000000000001'
pythonはこの問題を回避するためにstr()を使うときに最後の数桁を切り落としていると思いますが、それは部分的な回避策であり、何が起こっているのかを理解するには代えられません。
>>> str(.1)
'0.1'
丸め処理がどのような問題を引き起こしているのか、正確にはわかりません。 もしかすると、出力をより正確に制御する方法として、文字列のフォーマットを行う方が良いかもしれません。
例えば、以下のようになります。
>>> '%.5f' % .1
'0.10000'
>>> '%.5f' % .12345678
'0.12346'
ドキュメントはこちらをご覧ください。
len(repr(float(x)/3))
しかし、これは皆さんが思っているほど信頼できるものではないと言わざるを得ません。
浮動小数点数は10進数として入力/表示されますが、コンピュータ(実際には標準Cライブラリ)は2進数として保存します。この移行により、いくつかの副作用が発生します。
>>> print len(repr(0.1))
19
>>> print repr(0.1)
0.10000000000000001
なぜこのようなことが起こるのかについては、pythonチュートリアルのこの章で説明しています。
解決策としては、python'のdecimal.Decimal
のように、特に10進数を追跡する型を使用することです。
>>> print len(str(decimal.Decimal('0.1')))
3
他の回答でもすでに指摘されていますが、浮動小数点数の表現は、はっきり言って、茨の道です。
ご質問に十分な背景が書かれていないので、decimalモジュールがあなたのニーズに応えられるかどうかはわかりません。
http://docs.python.org/library/decimal.html
とりわけ、取得したい精度を明示的に指定することができます(ドキュメントより)。
>>> getcontext().prec = 6
>>> Decimal('3.0')
Decimal('3.0')
>>> Decimal('3.1415926535')
Decimal('3.1415926535')
>>> Decimal('3.1415926535') + Decimal('2.7182818285')
Decimal('5.85987')
>>> getcontext().rounding = ROUND_UP
>>> Decimal('3.1415926535') + Decimal('2.7182818285')
Decimal('5.85988')
簡単な例を私のプロンプト(python 2.6)から示します。
>>> import decimal
>>> a = decimal.Decimal('10.000000001')
>>> a
Decimal('10.000000001')
>>> print a
10.000000001
>>> b = decimal.Decimal('10.00000000000000000000000000900000002')
>>> print b
10.00000000000000000000000000900000002
>>> print str(b)
10.00000000000000000000000000900000002
>>> len(str(b/decimal.Decimal('3.0')))
29
これが役に立つかもしれません。 decimalはpython 2.4以降のstdlibに含まれており、python 2.6で追加されました。
お役に立てれば幸いです。 フランチェスコ