1. ホーム
  2. パイソン

[解決済み】最も近い整数に丸める

2022-03-30 08:33:31

質問

長い浮動小数点数の丸め方を教えてください。

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)

解決方法は?

TL;DR。

round(x)

は四捨五入して整数にします。

を代入しているわけではありません。 round(h) を変数に追加します。を呼び出すと round(h) この行を変更する必要があります。

h = round(h)

に新しい値を代入します。 h .


コメントで@plowmanが言っているように、Pythonの round() というのは、数値が変数として格納される方法は、通常、画面上で見る方法とは異なるからです。そこには たくさんの答え がこの挙動を説明しています。

この問題を回避する1つの方法は、次のようにDecimalを使用することです。 この回答 .

追加のライブラリを使用せずにこの回答を正しく動作させるには、カスタムの丸め関数を使用するのが便利でしょう。私は以下の解決策を思いつきました。私がテストした限りでは、すべての格納の問題を避けることができました。これは、文字列表現を使用することに基づいています。 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))


テスト

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

ここで厄介なのは dec -の小数点以下は9になり、もし dec+1 -が 0 になり、1 が加算されます。 dec-1 -ということです。

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

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 であり、以前のバージョンではただ単に ab を連結したものになります。 10 ここで、末尾の0は消えてしまいます。このバージョンでは b を元に、小数点以下右側へ dec を適切なキャリーとして使用します。