7

Pythonでいくつかの大きな数を分割しようとしていますが、奇妙な結果が得られています

NStr = "7D5E9B01D4DCF9A4B31D61E62F0B679C79695ACA70BACF184518" \
       "8BDF94B0B58FAF4A3E1C744C5F9BAB699ABD47BA842464EE93F4" \
       "9B151CC354B21D53DC0C7FADAC44E8F4BDF078F935D9D07A2C07" \
       "631D0DFB0B869713A9A83393CEC42D898516A28DDCDBEA13E87B" \
       "1F874BC8DC06AF03F219CE2EA4050FA996D30CE351257287" 

N = long(NStr, 16)
f2 = 476

fmin = N / float(f2)

print N - (fmin * float(f2))

これは期待どおりに出力さ0.0れます。ただし、たとえば、コードを次のように変更した場合

fmin = N / float(f2)
fmin += 1

私はまだの出力を取得します0.0

10進数パッケージも使ってみました

fmin = Decimal(N) / Decimal(f2)
print Decimal(N) - (fmin * Decimal(f2))

しかし、それは私に次の出力を与えます-1.481136900397802034028076389E+280

私はPythonに大きな数を適切に処理する方法を教えていないと思いますが、ここからどこに行くべきか悩んでいます。

また、最終目標は計算することです。

fmin = ceil(N / float(f2))

できるだけ長く正確に

4

6 に答える 6

7

私のコメントを拡張して、Nf2long厳密に0より大きい場合、

 fmin = (N - 1) // f2 + 1

正確ですceil(N / float(f2))(ただし、フロートを使用するよりも正確です)。

(整数除算では//なくの使用は/、Python 3.xとの互換性のためであり、余分な労力は必要ありません。)

それはN // f2あなたに(基本的に)与えるfloor(N / float(f2))のでN // f2 + 1、ほとんどの場合と同じceilです。ただし、Nがの倍数であるf2場合N // f2 + 1は大きすぎます(存在してはなり+1ません)が、を使用N - 1するとこれが修正され、他の場合は壊れません。

N(これは、f20以下では機能しませんが、個別に処理できます)

于 2012-04-12T11:07:27.043 に答える
4

fminfloat長整数をfloatで除算した後です。その値は1.84952718165824e+305です。これに1を追加しても、まったく変更されません。精度はそれほど高くありません。

代わりに整数除算を行う場合は、 :のfminままです。long

>>> fmin = N / f2
>>> fmin
18495271816582402193321106509793602189617847415669131056768139225220221855498293
49983070478076000952025038039460539798061570960870927236986153971731443029057201
52035339202255934728764897424408896865977423536890485615063959262845076766281553
766072964756078264853041334880929452289298495368916583660903481130L
>>> N - (fmin * f2)
111L

もちろん、0結果の小数部分が破棄される整数除算のため、取得できません。しかし今、1追加すると違いが生じます:

>>> N - ((fmin+1) * f2)
-365L

モジュールを使用してDecimalも問題は変わりません。

>>> from decimal import Decimal, getcontext
>>> fmin = Decimal(N) / Decimal(f2)
>>> fmin
Decimal('1.849527181658240219332110651E+305')

無制限の精度はまだありません。また、を設定しても、Decimal.getcontext().prec = 2000正確に0を取得することはできません。

于 2012-04-12T10:43:43.123 に答える
3

精度が必要な場合は、浮動小数点演算を完全に避けてください。Pythonには任意精度の整数があるため、基本的な整数演算を使用して除算の上限を計算できます。被除数と除数の両方が正であると仮定すると、それを行う方法は、除数の前に除数-1を被除数に追加することです。あなたの場合:

fmin = (N + f2 - 1) / f2

Python 3.xでは、整数除算を取得する//代わりに演算子を使用します。/

于 2012-04-12T11:28:18.827 に答える
2

Fractionfractionsモジュールからは役に立つかもしれません:

>  : N = Fraction(N)   
>  : f2 = Fraction(f2)
>  : fmin = N / f2
>  : print N-f2*fmin
0
>  : fmin += 1
>  : print N-f2*fmin
-476

ただし、計算が唯一の目標である場合は、ceil(N / float(f2))次を使用できます。

>  : fmin = N/f2 + int(ceil((N % f2) / float(f2)))
>  : print fmin
184952718165824021933211065097936021896178474156691310567681392252202218554982934998307047807600095202503803946053979806157096087092723698615397173144302905720152035339202255934728764897424408896865977423536890485615063959262845076766281553766072964756078264853041334880929452289298495368916583660903481131
于 2012-04-12T11:06:05.873 に答える
1

フロートは、この種の操作に十分な精度を備えていません。

decimalを使用すると、モジュールの精度を向上させることができますgetcontext()。たとえば、小数点以下65536桁を使用するには:

from decimal import Decimal, getcontext
getcontext().prec = 2**16

それで:

>>> print Decimal(N) - (fmin * Decimal(f2))
-2E-65228

まだ0ではありませんが近いです:)

オブジェクトに対してを行うには、この回答を参照してください。ceil()Decimal

于 2012-04-12T10:50:32.557 に答える
1

Python2.7.2でも同様の動作が見つかりました。

In [17]: N
Out[17]: 8803749384693223444020846698661754642258095369858506383021634271204825603217187705919415475641764531639181067832169438773077773745613648054092905441668
8183122792368821460273824930892091174018634908205253603559871152770444609114256540750019592650731223893254070047675403322419289706083795604293822590057017991L

In [18]:

In [18]: (fmin * float(f2))
Out[18]: 8.803749384693223e+307
In [19]: N - (fmin * float(f2))
Out[19]: 0.0

In [20]: (fmin * float(f2))
Out[20]: 8.803749384693223e+307

In [21]: N == (fmin * float(f2))
Out[21]: False

In [22]: N < (fmin * float(f2))
Out[22]: False

In [23]: N > (fmin * float(f2))
Out[23]: True

理由がわからないので、longからfloatを引くと0になるようです。

decimal.Decimal解決策は、両方を:に変換することであるように見えます。

In [32]: decimal.Decimal(N) - decimal.Decimal(fmin * float(f2))
Out[32]: Decimal('4.099850360284731589507226352E+291')
于 2012-04-12T10:52:52.540 に答える