web-dev-qa-db-ja.com

整数を他の整数より大きくする方法は?

注:受け入れられた答えは私が望む結果を達成し、@ ecatmurの答えはより包括的なオプションを提供しますが、そもそもユースケースが悪いアイデアであることを強調することは非常に重要だと感じています。これは @ Jason Orendorffの回答 で非常によく説明されています。

注:この質問は sys.maxintに関する質問 と重複していません。 sys.maxintとは関係ありません。 python 2でsys.maxintが利用可能な場合でも、最大整数を表しません(受け入れられた答えを参照)。

他の整数よりも大きい整数を作成する必要があります。つまり、>を使用して他のintオブジェクトと比較したときにTrueオブジェクトを返すintオブジェクトを意味します。ユースケース:ライブラリー関数は整数を予期し、特定の動作を強制する唯一の簡単な方法は、非常に大きな整数を渡すことです。

python 2、sys.maxintを使用できます(編集:私は間違っていました)。python 3、math.infが最も近い同等ですが、intに変換できません。

50
max

python整数は無制限なので、これをカスタムクラスで行う必要があります。

import functools

@functools.total_ordering
class NeverSmaller(object):
    def __le__(self, other):
        return False

class ReallyMaxInt(NeverSmaller, int):
    def __repr__(self):
        return 'ReallyMaxInt()'

ここでは、NeverSmallerを直接装飾するのではなく、ミックスインクラスReallyMaxIntを使用しました。なぜなら、Python 3のアクションはfunctools.total_orderingintから継承された既存の順序付けメソッドによって防止されています。

使用デモ:

>>> N = ReallyMaxInt()
>>> N > sys.maxsize
True
>>> isinstance(N, int)
True
>>> sorted([1, N, 0, 9999, sys.maxsize])
[0, 1, 9999, 9223372036854775807, ReallyMaxInt()]

Python2では、sys.maxint + 1sys.maxintよりも大きいため、それに頼ることはできません。

免責事項:これは [〜#〜] oo [〜#〜] の意味の整数であり、数学的な意味での整数。そのため、親クラスintから継承した算術演算は適切に動作しない場合があります。これにより、意図したユースケースで問題が発生する場合は、__add__およびフレンドを実装することでエラーを無効にすることができます。

67
wim

Konsta Vesterinenの infinity.Infinity は機能します( pypi )。ただし、intを継承しないが、サブクラス化できます。

from infinity import Infinity
class IntInfinity(Infinity, int):
    pass
assert isinstance(IntInfinity(), int)
assert IntInfinity() > 1e100

「無限大」値を実装する別のパッケージは Extremes で、拒否されたものから回収されました PEP 326 ;ここでも、extremes.Maxおよびintからサブクラス化する必要があります。

27
ecatmur

ユースケース:ライブラリー関数は整数を予期し、特定の動作を強制する唯一の簡単な方法は、非常に大きな整数を渡すことです。

これはライブラリの欠陥のように聞こえますが、ライブラリのインターフェースで修正する必要があります。その後、そのすべてのユーザーが恩恵を受けるでしょう。それはどの図書館ですか?

オーバーライドされた比較演算子を使用して、魔法のintサブクラスを作成するとうまくいく場合があります。しかし、それはもろいです。ライブラリがそのオブジェクトをどのように処理するかはわかりません。文字列に変換するとします。何が起こるべきですか?また、ライブラリが進化するにつれて、データはさまざまな方法で自然に使用されます。いつかライブラリを更新して、トリックが機能しないことを確認することができます。

15
Jason Orendorff

これは基本的に不可能であるように思えます。このRBI(「本当に大きなint」)を返す関数を書いたとしましょう。コンピュータがそれを保存できる場合、他の誰かが同じ値を返す関数を書くことができます。あなたのRBIはそれ自体よりも大きいですか?

おそらく、@ wimの答えのようなもので目的の結果を達成できます。比較演算子をオーバーライドするオブジェクトを作成して、「<」が常にfalseを返し、「>」が常にtrueを返すようにします。 (私は多くのPythonを書いたことはありません。ほとんどのオブジェクト指向言語では、RBI> xの場合、比較によって値が最初になった場合にのみ機能します。コンパイラは整数とユーザー定義クラスを比較する方法を知らないため失敗します。)

1
Jay

Python 3.5、you can do:

import math test = math.inf

その後:

test > 1 test > 10000 test > x

常に真実です。もちろん、指摘されているように、xも無限または「nan」(「not a number」)です。

Pythonで無限数を表現するにはどうすればよいですか?

@WilHallによる回答

1
R__raki__

interfaceimplementationの両方が必要な場合を除き、intから継承しないでください。 (その実装は、有限数を表すビットの自動拡張セットです。明らかにそれは必要ありません。)interfaceのみが必要なため、ABC Integralを継承します。 @ecatmurの回答のおかげで、infinityを使用して、無限の核心(否定を含む)に対処できます。 infinityをABC Integralと組み合わせる方法は次のとおりです。

import pytest
from infinity import Infinity
from numbers import Integral


class IntegerInfinity(Infinity, Integral):

    def __and__(self, other):
        raise NotImplementedError

    def __ceil__(self):
        raise NotImplementedError

    def __floor__(self):
        raise NotImplementedError

    def __int__(self):
        raise NotImplementedError

    def __invert__(self, other):
        raise NotImplementedError

    def __lshift__(self, other):
        raise NotImplementedError

    def __mod__(self, other):
        raise NotImplementedError

    def __or__(self, other):
        raise NotImplementedError

    def __Rand__(self, other):
        raise NotImplementedError

    def __rlshift__(self, other):
        raise NotImplementedError

    def __rmod__(self, other):
        raise NotImplementedError

    def __ror__(self, other):
        raise NotImplementedError

    def __round__(self):
        raise NotImplementedError

    def __rrshift__(self, other):
        raise NotImplementedError

    def __rshift__(self, other):
        raise NotImplementedError

    def __rxor__(self, other):
        raise NotImplementedError

    def __trunc__(self):
        raise NotImplementedError

    def __xor__(self, other):
        raise NotImplementedError

def test():
    x = IntegerInfinity()
    assert x > 2
    assert not x < 3
    assert x >= 5
    assert not x <= -10
    assert x == x
    assert not x > x
    assert not x < x
    assert x >= x
    assert x <= x
    assert -x == -x
    assert -x <= -x
    assert -x <= x
    assert -x < x
    assert -x < -1000
    assert not -x < -x
    with pytest.raises(Exception):
        int(x)
    with pytest.raises(Exception):
        x | x
    with pytest.raises(Exception):
        ceil(x)

これはpytestで実行して、必要な不変条件を検証できます。

0
Neil G