2013-08-07 7 views
14

Pythonの浮動小数点数に 'one'を追加する簡単で直接的な方法はありますか?Pythonで浮動小数点数を1にするには?

私はこの意味:それは私に0.0144000000001を与えるので、これは、私が欲しいものではありません

if a == 0.0143: 
    a = plus(a) 
    assert a == 0.0144 

def plus(a): 
    sa = str(a) 
    index = sa.find('.') 
    if index<0: 
     return a+1 
    else: 
     sb = '0'*len(sa) 
     sb[index] = '.' 
     sb[-1] = 1 
     return a+float(sb) 

を。あなたが気づいてきたよう

+1

これは素晴らしい質問です。質問してくれてありがとう。 – zsong

答えて

20

、必ずしもすべての小数は正確に浮動小数点数として表すことができます。

>>> Decimal(0.1) 
Decimal('0.1000000000000000055511151231257827021181583404541015625') 
>>> Decimal(0.2) 
Decimal('0.200000000000000011102230246251565404236316680908203125') 
>>> Decimal(0.3) 
Decimal('0.299999999999999988897769753748434595763683319091796875') 
>>> Decimal(0.4) 
Decimal('0.40000000000000002220446049250313080847263336181640625') 
>>> Decimal(0.5) 
Decimal('0.5') 

あなたが小数のプロパティで作業しているので、正確にそれらを実装decimalモジュールを、使用します。

from decimal import Decimal 

def plus(n): 
    return n + Decimal('10') ** n.as_tuple().exponent 

とデモ:

>>> n = Decimal('0.1239') 
>>> plus(n) 
Decimal('0.1240') 

Y浮動小数点数は精度を失うので、数値を文字列として表現する必要があります。

Decimalを使用すると、plusの機能が浮動小数点演算を使用した場合よりも約20〜30倍遅くなりますが、それは精度のコストです。

+0

+1は実際に読み取り可能です。このようなことをすることは、コードの混乱を避けるためにとても簡単です。 – jpmc26

+0

@Blenderこれは素晴らしいです。 – zsong

+0

Python 3.3の時点では、 'decimal'モジュールはC言語で実装されているので、floatを使用するよりもはるかに遅くすべきではないことに注意してください。 –

2

Blenderの答えは間違いなく良い答えですが、あなたはfloatsを使用することを主張すれば、私はこれを行うための簡単な方法があると信じて:

  1. は、整数にあなたのフロートを掛けることができ10 ** xのためのxをご覧ください。

  2. 拡大数字に1を加えます。

  3. 前の乗数を除算します。

    n = 0.125 
    e = len(str(n)) - 2 
    temp_n = n * 10 ** e 
    temp_n += 1 
    n = temp_n/10 ** e 
    print n 
    

    EDIT:

だから、のように見える数が非常に長かったとき、前のスクリプトで

、物事が間違っていました。結果はstr()printによって切り捨てので、私は、スクリプトを少し変更されます。

n = 0.1259287345982795 
e = len(repr(n)) - 2 
temp_n = n * 10 ** e 
temp_n += 1 
n = temp_n/10 ** e 
print repr(n) 
+0

nが非常に小さい場合は動作しません。 'n = 0.125928734598279'、結果は' 0.125928734599' – zsong

+0

ああ、 'str()'と 'print'は長い文字列を切り捨てるからです。'repr()'の助けを借りてすべてがうまくいきます:)私は私の投稿を更新します。 – shengy

+0

あなたは '10 ** e'で除算をスキップし、' n + 10 ** - e'を実行することができます – Blender

0
n = n + 1/10**(len(repr(n)) - 2) 
+0

手入れをするのに気をつけますか? –

+0

@blenderによって提案されているように、 'n = n + 10 ** - (len(repr(n)) - 2)'がさらに優れています。詳細については、@ shengyの最初の回答を参照してください。私はちょうどそれを圧縮し、それを修正するために 'repr'を使いました。 – dansalmo

関連する問題