数値を最も近い整数に丸める


230

私は長い浮動小数点数を次のように丸めようとしています:

32.268907563;
32.268907563;
31.2396694215;
33.6206896552;
...

今のところ成功していません。私はを試してみましたmath.ceil(x)math.floor(x)(切り上げたり切り捨てたりするので、探しているものではありません)、round(x)どちらも機能しませんでした(まだ浮動小数点数です)。

私は何ができますか?

編集:コード:

for i in widthRange:
    for j in heightRange:
        r, g, b = rgb_im.getpixel((i, j))
        h, s, v = colorsys.rgb_to_hsv(r/255.0, g/255.0, b/255.0)
        h = h * 360
        int(round(h))
        print(h)

3
私が試してみるint(x)
Brofessor

エラーにならないでしょうか?ベース10のint()の無効なリテラル:
snh_nl

回答:


366
int(round(x))

丸め、整数に変更します

編集:

int(round(h))を変数に割り当てていません。int(round(h))を呼び出すと、整数が返されますが、それ以外は何も行われません。次の行を変更する必要があります。

h = int(round(h))

新しい値をhに割り当てるには

編集2:

@plowmanがコメントで述べたように、Python round()は通常のように機能しません。これは、数値が変数として格納される方法が通常、画面に表示される方法と異なるためです。この動作を説明する多くの答えがあります:

round()が適切に丸められていないようです

この問題を回避する1つの方法は、この回答で述べられているように10進数を使用することです:https : //stackoverflow.com/a/15398691/4345659

追加のライブラリを使用せずにこの回答を適切に機能させるには、カスタム丸め関数を使用すると便利です。多くの修正の後、私がテストした限り、すべての保存の問題を回避した次の解決策を思いつきました。repr()(NOT str()!)で取得した文字列表現の使用に基づいています。見た目はハックですが、すべてのケースを解決するために私が見つけた唯一の方法でした。Python2とPython3の両方で動作します。

def proper_round(num, dec=0):
    num = str(num)[:str(num).index('.')+dec+2]
    if num[-1]>='5':
        return float(num[:-2-(not dec)]+str(int(num[-2-(not dec)])+1))
    return float(num[:-1])

テスト:

>>> print(proper_round(1.0005,3))
1.001
>>> print(proper_round(2.0005,3))
2.001
>>> print(proper_round(3.0005,3))
3.001
>>> print(proper_round(4.0005,3))
4.001
>>> print(proper_round(5.0005,3))
5.001
>>> print(proper_round(1.005,2))
1.01
>>> print(proper_round(2.005,2))
2.01
>>> print(proper_round(3.005,2))
3.01
>>> print(proper_round(4.005,2))
4.01
>>> print(proper_round(5.005,2))
5.01
>>> print(proper_round(1.05,1))
1.1
>>> print(proper_round(2.05,1))
2.1
>>> print(proper_round(3.05,1))
3.1
>>> print(proper_round(4.05,1))
4.1
>>> print(proper_round(5.05,1))
5.1
>>> print(proper_round(1.5))
2.0
>>> print(proper_round(2.5))
3.0
>>> print(proper_round(3.5))
4.0
>>> print(proper_round(4.5))
5.0
>>> print(proper_round(5.5))
6.0
>>> 
>>> print(proper_round(1.000499999999,3))
1.0
>>> print(proper_round(2.000499999999,3))
2.0
>>> print(proper_round(3.000499999999,3))
3.0
>>> print(proper_round(4.000499999999,3))
4.0
>>> print(proper_round(5.000499999999,3))
5.0
>>> print(proper_round(1.00499999999,2))
1.0
>>> print(proper_round(2.00499999999,2))
2.0
>>> print(proper_round(3.00499999999,2))
3.0
>>> print(proper_round(4.00499999999,2))
4.0
>>> print(proper_round(5.00499999999,2))
5.0
>>> print(proper_round(1.0499999999,1))
1.0
>>> print(proper_round(2.0499999999,1))
2.0
>>> print(proper_round(3.0499999999,1))
3.0
>>> print(proper_round(4.0499999999,1))
4.0
>>> print(proper_round(5.0499999999,1))
5.0
>>> print(proper_round(1.499999999))
1.0
>>> print(proper_round(2.499999999))
2.0
>>> print(proper_round(3.499999999))
3.0
>>> print(proper_round(4.499999999))
4.0
>>> print(proper_round(5.499999999))
5.0

最後に、正しい答えは次のとおりです。

# Having proper_round defined as previously stated
h = int(proper_round(h))

編集3:

テスト:

>>> proper_round(6.39764125, 2)
6.31 # should be 6.4
>>> proper_round(6.9764125, 1)
6.1  # should be 7

ここでの落とし穴は、dec-thの10進数が9になる可能性があることです。- dec+1thの桁> = 5の場合、9は0になり、1がdec-1-thの桁に送られます。

これを考慮すると、次のようになります。

def proper_round(num, dec=0):
    num = str(num)[:str(num).index('.')+dec+2]
    if num[-1]>='5':
      a = num[:-2-(not dec)]       # integer part
      b = int(num[-2-(not dec)])+1 # decimal part
      return float(a)+b**(-dec+1) if a and b == 10 else float(a+str(b))
    return float(num[:-1])

上述した状況においてb = 10、および以前のバージョンのと同じCONCATENATE abの連結をもたらすであろう10後続0が消えてしまう場合。このバージョンは、適切な桁上げとして、にb基づいて正しい小数点以下の桁に変換されdecます。


2
print( "4.5)"、int(round(4.5)))#4を与えたprint( "5.5)"、int(round(5.5)))#6を与えた:、(
Komm

Pythonのバージョンに関連しています。Python 2.7.9を使用して5と6を提供し、あなたが言ったように、Python 3.4.2を使用して4と6を
取得します

1
注目に値する:このソリューションは、おそらくあなたが期待する方法で丸めません。例えば、int(round(4.5))4までラウンドしながら、int(round(4.500001))正しく5に丸め
プロウマン

整数round(x)が必要な場合は、Python 3.6.2(およびおそらくそれよりも低いバージョン)で十分です。結果はすでに型intです。注:round(x, n)float型になります。
Elmex80s

1
これは112439.50093565206では機能しません。o / p-> 11253.0になります。気味が悪い.. !!!!!!
ajin

24

を使用しround(x, y)ます。それはあなたの数をあなたの望ましい小数位に切り上げます。

例えば:

>>> round(32.268907563, 3)
32.269

20

round(value,significantDigit)は通常の解決策ですが、これは、末尾がで終わる値を丸めるときに数学の観点から期待するようには機能しません55が丸められた直後の桁にある場合、これらの値は期待どおりに切り上げられるだけです(つまり8.005、2桁の10進数に丸めると、になります8.01)。浮動小数点演算の癖による特定の値については、代わりに切り捨てられます!

すなわち

>>> round(1.0005,3)
1.0
>>> round(2.0005,3)
2.001
>>> round(3.0005,3)
3.001
>>> round(4.0005,3)
4.0
>>> round(1.005,2)
1.0
>>> round(5.005,2)
5.0
>>> round(6.005,2)
6.0
>>> round(7.005,2)
7.0
>>> round(3.005,2)
3.0
>>> round(8.005,2)
8.01

変。

あなたの意図が科学の統計のための伝統的な丸めを行うことであると仮定すると、これはround関数を期待どおりに機能させるための便利なラッパーであり、などのimport追加のものを必要としDecimalます。

>>> round(0.075,2)

0.07

>>> round(0.075+10**(-2*5),2)

0.08

ああ!これに基づいて、関数を作成できます...

def roundTraditional(val,digits):
   return round(val+10**(-len(str(val))-1), digits)

基本的に、これにより、使用しようとしている文字列の指定された最小桁よりも小さいことが保証される値が追加されますround。その少量を追加することによりround、ほとんどの場合での動作が保持され、丸められる桁よりも低い桁が切り上げられるか、切り捨てられる5かが確認4されます。

使用するアプローチ10**(-len(val)-1)は慎重に行った。シフトを強制するために追加できる最大の小さい数であり、小数.が欠落している場合でも、追加する値が丸めを変更しないことを保証する。私は使用することができ10**(-len(val))condiditionalをif (val>1)減算する1より...しかし、それだけで常に減算する方が簡単だ1とはこの回避策を適切に処理することができ進数の多くの適用範囲を変更しません。値が型の制限に達した場合、このアプローチは失敗しますが、これは失敗しますが、有効な10進数値のほぼすべての範囲で機能します。

10進ライブラリーを使用してこれを実現することもできますが、私が提案するラッパーはより単純で、場合によっては優先される場合があります。


編集:フリンジケースが特定の値でのみ発生することを指摘してくれたBlckknghtに感謝し5ます。また、この回答の以前のバージョンでは、丸めている桁のすぐ下の桁にがある場合にのみ5奇数丸め動作が発生するほど明確ではありませんでし


5最後の桁がである小数が常に切り捨てられると思う理由がわかりません。それは私がちょうどのような数字で行った簡単なテストケースではありません1.52.53.5などと1.051.151.251.35、小数点以下1桁に丸めます。最初のセット(小さな整数に丸める正確な半分)は常に偶数の整数に丸めます。おそらく一部の値の不正確なバイナリ表現が原因で、後者のセットは一貫して丸められません。1.25丸めのような正確なバイナリ表現を持つ浮動小数点数は、最下位の桁までありますが、その他はランダムに丸められているように見えます。
Blckknght 2016

おもしろい…そうだ。 round(4.0005,3)与える4.0round(1.0005,3)与える1.0round(2.0005,3)与える2.001round(3.0005,3)与える3.001。しかし、それがまさに私の提案するソリューションが必要な理由です...この重要なケースでは、株式ラウンドから何を期待するのかわかりません!
Jason R. Mick

これをありがとう。この問題が発生すると、関数が役立ちます。
TMWP 2017

1
あなたが持っているもしかして, digitsそのreturn文の末尾に?しゃれは意図されていません。(平均 I平均)
user3342816

ああ、正解です。良いキャッチ...他の誰も気づいていないことに驚いた!このソリューションを利用する人たちをいらいらさせることはありません。:-)
ジェイソンR.ミック

15

ポジティブについては、

int(x + 0.5)

ネガにも使えるようにするには、

int(x + (0.5 if x > 0 else -0.5))

int()は床関数のように機能するため、このプロパティを利用できます。これは間違いなく最速の方法です。


4
ネガには使用できません>>> x=-0.999 >>> int(x), round(x), int(x+0.5) (0, -1.0, 0)
user2907934

3
コーナーケースが気になる場合は、「0.5と床を追加する」手法を使用しないでください。期待どおりに丸められない可能性がある値があります。C ++テイクについては、stackoverflow.com / a / 47302585/2732969を参照してください。この質問に対するstackoverflow.com/a/38744026/2732969の回答もご覧ください。
Anon

高速な方法が必要でした。正確である必要はなく、コーナーケースが多くなく、コーナーケースのエラーは私のシナリオでは重要ではありません。ですから、速度が優先されるいくつかの特別なケースでは、これが間違いなく私のお気に入りです。精度や正確さのために推奨しないでください。
AgentM

11

IEEE 754で規定されているように、Pythonは単に半分から半分に丸めているのではないですか?

注意深く再定義するか、「非標準」の丸めを使用してください…

https://stackoverflow.com/a/33019948/109839も参照してください


2
この答えは少し不明確です。Round half to evenIEEE 754では絶対的に規定されていませんが、標準で説明されているいくつかの丸めオプションの1つにすぎません。Round to nearest, ties away from zero(つまり、ほとんどの人が期待する動作)もオプションであり、たとえばC / C ++ではデフォルトです。
電話

私は同意します、その表現はかなり混乱します。Pythonがヘブンに丸めていることを意味している(docs.python.org/3.7/library/の最後にある表を参照してください。ここroundで説明されています)。これは、「四捨五入」が規定されている方法に従って行われます。標準で機能する(または説明される)
Mapio

8

python3.xを使用している場合はnumpyを使用することもできます。ここに例を示します。

import numpy as np
x = 2.3
print(np.rint(x))
>>> 2.0

7

あなたの解決策は、2番目の引数(小数点以下の桁数)を指定せずにラウンドを呼び出すことです

>>> round(0.44)
0
>>> round(0.64)
1

これはよりもはるかに良い結果です

>>> int(round(0.44, 2))
0
>>> int(round(0.64, 2))
0

https://docs.python.org/3/library/functions.html#roundにあるPythonドキュメントから

丸め(数値[、n桁])

小数点以下n桁の精度に丸めた数値を返します。ndigitsが省略されているかNoneの場合、入力に最も近い整数を返します。

注意

floatのround()の動作は驚くべきものになる可能性があります。たとえば、round(2.675、2)は、期待される2.68ではなく2.67を返します。これはバグではありません。これは、ほとんどの小数部が浮動小数点として正確に表現できないという事実の結果です。詳細については、浮動小数点演算:問題と制限を参照してください。


1

(たとえば)Aに2桁の近似 int(A*100+0.5)/100.0が必要な場合は、探していることを実行します。

3桁の近似値が必要な場合は、1000で乗算して除算します。


1

このようなこともうまくいくはずです

import numpy as np    

def proper_round(a):
    '''
    given any real number 'a' returns an integer closest to 'a'
    '''
    a_ceil = np.ceil(a)
    a_floor = np.floor(a)
    if np.abs(a_ceil - a) < np.abs(a_floor - a):
        return int(a_ceil)
    else:
        return int(a_floor)

0

この目的のために、私は次のことを行うことをお勧めします-

int(round(x))

これにより、最も近い整数が得られます。

お役に立てれば!!


0

私は使用し、次の解決策をアドバイスすることがあります(python3.6):

y = int(x + (x % (1 if x >= 0 else -1)))

半数(正と負)に対しては正常に機能し、int(round(x))よりも高速に機能します。

round_methods = [lambda x: int(round(x)), 
                 lambda x: int(x + (x % (1 if x >= 0 else -1))),
                 lambda x: np.rint(x).astype(int),
                 lambda x: int(proper_round(x))]

for rm in round_methods:
    %timeit rm(112.5)
Out:
201 ns ± 3.96 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
159 ns ± 0.646 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
925 ns ± 7.66 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
1.18 µs ± 8.66 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

for rm in round_methods:
    print(rm(112.4), rm(112.5), rm(112.6))
    print(rm(-12.4), rm(-12.5), rm(-12.6))
    print('=' * 11)

Out:
112 112 113
-12 -12 -13
===========
112 113 113
-12 -13 -13
===========
112 112 113
-12 -12 -13
===========
112 113 113
-12 -13 -13
===========
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.