web-dev-qa-db-ja.com

Pythonでfloatを整数に変換する最も安全な方法は?

Pythonの数学モジュールはfloorceilのような便利な関数を含みます。これらの関数は浮動小数点数を取り、それより下または上の最も近い整数を返します。ただし、これらの関数は答えを浮動小数点数として返します。例えば:

import math
f=math.floor(2.3)

fは以下を返します。

2.0

丸め誤差の危険を冒さずにこの浮動小数点から整数を取り出す最も安全な方法は何ですか(たとえば、浮動小数点数が1.99999に相当する場合)、それとも別の関数をすべて使用するべきですか

181
Boaz

浮動小数点数で表すことができるすべての整数は正確な表現を持ちます。だからあなたは安全に結果にintを使うことができます。不正確な表現は、2のべき乗ではない分母を使って有理数を表現しようとしている場合にのみ発生します。

これがうまくいくことは決して簡単ではありません!問題となる数値の大きさが十分に小さければ、それはint○floo =⌊・thatとなるIEEE浮動小数点表現の特性ですが、int(floor(2.3))が1の場合は異なる表現が可能です。

ウィキペディア から引用するには、

絶対値が2以下の任意の整数24 単精度形式、および絶対値が2以下の任意の整数で正確に表すことができます。53 倍精度形式で正確に表すことができます。

156
Philipp

int(your non integer number)を使うとうまくいきます。

print int(2.3) # "2"
print int(math.sqrt(5)) # "2"
96
srodriguex

あなたはround関数を使うことができます。あなたが2番目のパラメータ(有効数字の桁数)を使用しないなら、私はあなたが望む振る舞いを得るだろうと思います。

IDLE出力.

>>> round(2.99999999999)
3
>>> round(2.6)
3
>>> round(2.5)
3
>>> round(2.4)
2
44
Wade73

前の2つの結果を組み合わせると、次のようになります。

int(round(some_float))

これは、floatをかなり確実に整数に変換します。

38
user3763109

これが機能するということは決して些細なことではありません!問題の数値の大きさが十分に小さい場合、int∘floor= thatというIEEE浮動小数点表現のプロパティですが、int(floor(2.3))が1の場合は異なる表現が可能です。

この投稿では、その範囲で機能する理由を説明しています

Doubleでは、32ビット整数を問題なく表現できます。丸めの問題はできません。より正確には、doubleはall2の間の整数を表すことができます53および-253

簡単な説明:doubleは最大53桁の2進数を格納できます。さらに必要な場合は、右側にゼロが埋め込まれます。

つまり、53個がパディングなしで保存できる最大数です。当然、必要な桁数が少ないすべての(整数)数値を正確に格納できます。

1を111(omitted)111(53個)に追加すると、100 ... 000、(53個のゼロ)が生成されます。ご存知のように、53桁を格納できます。これにより、右端のゼロパディングが作成されます。

これは253 から来た。


詳細: IEEE-754浮動小数点の動作を考慮する必要があります。

  1 bit    11 / 8     52 / 23      # bits double/single precision
[ sign |  exponent | mantissa ]

次に、数は次のように計算されます(ここでは無関係な特別な場合を除く)。

-1符号 ×1.仮数×2指数-バイアス

ここで、bias = 2指数-1 -1、つまり、それぞれ倍精度/単精度の場合は1023と127です。

2で乗算することを知っているバツ単にすべてのビットをシフトしますX位置を左に移動します。すべての整数がすべてのビットを持たなければならないことは簡単にわかります。小数点の右側がゼロになる仮数で。

ゼロ以外の整数のバイナリ形式は次のとおりです。

1x ... xここで、x-esはビットを表しますMSBの右側(最上位ビット)。

ゼロを除外したため、常にalwaysが1つのMSBになります。これが格納されない理由です。整数を格納するには、前述の形式にする必要があります:-1符号 ×1.仮数×2指数-バイアス

これは、MSBの左側にMSBだけが現れるまで、ビットを小数点でシフトするのと同じことを言っています。小数点の右側のすべてのビットは仮数に格納されます。

これから、MSB以外に最大52桁の2進数を格納できることがわかります。

したがって、すべてのビットが明示的に保存される最大数は

111(omitted)111.   that's 53 ones (52 + implicit 1) in the case of doubles.

このため、小数点が52桁シフトするように、指数を設定する必要があります。指数を1増加させると、小数点の直後の桁を知ることができません。

111(omitted)111x.

慣例により、それは0です。仮数部全体をゼロに設定すると、次の番号が返されます。

100(omitted)00x. = 100(omitted)000.

これは、1に53個のゼロが続き、52個が格納され、指数のために1が追加されます。

2を表します53、すべての整数を正確に表すことができる境界(負と正の両方)をマークします。 2に1を追加したい場合53、暗黙のゼロ(xで示される)を1に設定する必要がありますが、それは不可能です。

18
phant0m

math.floorは常に整数を返すので、int(math.floor(some_float))は丸め誤差を招くことは決してありません。

ただし、丸め誤差はmath.floor(some_large_float)ですでに導入されている可能性があります。または、そもそもfloatに大量に格納する場合でも同様です。 (大きい数値はフロートに格納すると精度が落ちる可能性があります。)

6
user3850

文字列floatをintに変換する必要があるなら、このメソッドを使うことができます。

例:'38.0'から38

これをint型に変換するためには、float型にキャストしてからint型にキャストすることができます。これはfloat文字列またはinteger文字列に対しても機能します。

>>> int(float('38.0'))
38
>>> int(float('38'))
38

:これは小数点以下の数字を削除します。

>>> int(float('38.2'))
38
5
brandonbanks

変数を使用して実数/浮動小数点数を整数に変換するもう1つのコードサンプル。 "vel"は実数/浮動小数点数で、次に大きいINTEGERの "newvel"に変換されます。

import arcpy.math, os, sys, arcpy.da
.
.
with arcpy.da.SearchCursor(densifybkp,[floseg,vel,Length]) as cursor:
 for row in cursor:
    curvel = float(row[1])
    newvel = int(math.ceil(curvel))
1
mrichey56

あなたが '最も安全な'方法を求めているので、私は一番上の答え以外のもう一つの答えを提供します。

精度を落とさないようにする簡単な方法は、変換後に値が等しくなるかどうかを確認することです。

if int(some_value) == some_value:
     some_value = int(some_value)

たとえばfloatが1.0の場合、1.0は1になります。したがって、intへの変換が実行されます。 floatが1.1の場合、int(1.1)は1に等しく、1.1!= 1になります。したがって、値はfloatのままになり、精度を失うことはありません。

0
Troy H