web-dev-qa-db-ja.com

Pythonでは、整数除算でゼロに向かって丸めるための良い方法は何ですか?

1/2

与える

0

それがあるべきように。しかしながら、

-1/2

与える

-1

、しかし、それが正か負かに関係なく、0に丸めたい(つまり、-1/2を0にしたい)。それを行う最良の方法は何ですか?

18
blacktrance

浮動小数点除算を行ってから、intに変換します。追加のモジュールは必要ありません。

>>> int(float(-1)/2)
0
>>> int(float(-3)/2)
-1
>>> int(float(1)/2)
0
>>> int(float(3)/2)
1
15
Tim

Pythonのデフォルトの整数の除算では、下限を(負の無限大に向かって)返し、それを変更することはできません。 read BDFLの理由。

「切り上げ」除算を行うには、次のようにします。

>>> a=1
>>> b=2
>>> (a+(-a%b))//b
1
>>> a,b=-1,2
>>> (a+(-a%b))//b
0

ゼロへの切り捨てを行い、整数除算を維持するには、aまたはbのいずれかが負の場合は(a+(-a%b))//bを使用し、両方が正の場合はデフォルトの除算を使用します。

これは整数除算を行い、常にゼロに向かって丸めます。

>>> a=1
>>> b=2
>>> a//b if a*b>0 else (a+(-a%b))//b
0
>>> a=-1
>>> b=2
>>> a//b if a*b>0 else (a+(-a%b))//b
0
>>> a,b=-3,2
>>> a//b if a*b>0 else (a+(-a%b))//b
-1
>>> a,b=3,2
>>> a//b if a*b>0 else (a+(-a%b))//b
1

脚注

興味深いことに、C99は ゼロに向かって丸める がデフォルトであることを宣言しています。

#include <stdio.h>
int main(int argc, const char * argv[])
{

    int a=-3;
    int b=2;
    printf("a=%d, b=%d, a/b=%d\n",a,b,a/b);
    a=3;
    printf("a=%d, b=%d, a/b=%d\n",a,b,a/b);
    return 0;
}

プリント:

a=-3, b=2, a/b=-1
a=3, b=2, a/b=1
5
dawg

それだけの価値があるので、私自身のお気に入りのソリューションはこれです。整数演算のみ、単一の除算、およびその他すべての線形時間:

def integer_divide_towards_zero(a, b):
    return -(-a // b) if a < 0 else a // b

これはbが正であることを前提としていますが、私が見たほとんどのアプリケーションではそれが真実です。負のbも処理する必要がある場合、関数はわずかに複雑になります。

def integer_divide_towards_zero(a, b):
    return -(-a // b) if (a < 0) ^ (b < 0) else a // b

いくつかのサンプル出力:

>>> integer_divide_towards_zero(11, 3)
3
>>> integer_divide_towards_zero(-11, 3)
-3
>>> integer_divide_towards_zero(6, 3)
2
>>> integer_divide_towards_zero(-6, 3)
-2
>>> integer_divide_towards_zero(11, -3)
-3
>>> integer_divide_towards_zero(-11, -3)
3
4
Mark Dickinson

これを試して。 -1より大きい数値でのみ機能します

import math

x = .5
y = -.5

print math.floor(math.fabs(x))
>> 0

print math.floor(math.fabs(y))
>> 0
1
Conor Patrick

いくつかの別のアイデアで私の帽子を投げ込みます:

数の符号[abs(x)/ x]とabs(x)/ 2の倍数

(abs(x)/x)*(abs(x)/2)

加算を実行しますが、数値がゼロより小さい場合は、1を加算して0に近づけます。

x/2 + int(x<0)
1
user764357

Decimal モジュールを標準のpythonライブラリの一部として使用することもできます。

具体的には、 "整数除算演算子//も同様に動作し、通常のIDを保存するために、床ではなく真の商の整数部分(ゼロに向かって切り捨て)を返しますx ==(x // y)* y + x %y: "

>>> -7 // 4
-2
>>> Decimal(-7) // Decimal(4)
Decimal('-1')

また、 丸めモード も確認してください。情報を表示/丸めるには、天井、下、床、ハーフダウン、ハーフイーブン、ハーフアップ、アップのかなり多くの方法があります。そして05up丸め。

Decimalは、10進解を期待する世界における2進数学の伝統的な問題の解決策として作成されました

1
jjisnow

これを行うための正しいコードは、私の意見では、1ライナーとして書くにはあまりにもあいまいです。だから私はそれを次のような関数に入れます:

def int0div(a, b):
    q = a // b
    if q < 0 and b*q != a:
        q += 1
    return q

優れた機能:あらゆるサイズのintで機能し、raw(a//b)必要な場合を除き、1つの除算(%もカバーの下で除算を行い、入力より大きな整数を作成しません。これらはアプリケーションで重要な場合と重要でない場合があります。 「ビッグ」整数を使用する場合、(速度のために)それらはより重要になります。

1
Tim Peters

完全に優れたmath.trunc()関数があるのに、なぜホイールを再発明するのですか?

import math
print(math.trunc(-3.5))
>>-3
print(math.trunc(3.5))
>>3
0
jjisnow