>>> (float('inf')+0j)*1
(inf+nanj)
どうして?これにより、コードに厄介なバグが発生しました。
なぜ1
乗法的アイデンティティは与え(inf + 0j)
ないのですか?
>>> (float('inf')+0j)*1
(inf+nanj)
どうして?これにより、コードに厄介なバグが発生しました。
なぜ1
乗法的アイデンティティは与え(inf + 0j)
ないのですか?
回答:
1
最初の複素数に変換され1 + 0j
、その後につながり、inf * 0
その結果、乗算nan
。
(inf + 0j) * 1
(inf + 0j) * (1 + 0j)
inf * 1 + inf * 0j + 0j * 1 + 0j * 0j
# ^ this is where it comes from
inf + nan j + 0j - 0
inf + nan j
1
がにキャストされる最初のステップです1 + 0j
。
array([inf+0j])*1
も評価されarray([inf+nanj])
ます。実際の乗算がC / C ++コードのどこかで発生するとすると、これは、_Complexやstd :: complexを使用するのではなく、CPythonの動作をエミュレートするカスタムコードを作成したことを意味しますか?
numpy
にはufunc
、ほぼすべての演算子と関数が派生する1つの中心的なクラスがあります。ufunc
ブロードキャストの管理は、アレイの操作を非常に便利にするトリッキーな管理をすべて処理します。より正確には、特定の演算子と一般的な機械の間の労働の分割は、特定の演算子が、処理したい入力要素と出力要素のタイプの組み合わせごとに、「最も内側のループ」のセットを実装することです。一般的な機械は、外側のループを処理し、最も内側のループに最も一致するものを選択します...
types
属性を介して、提供された内部ループのリストにアクセスできます。特に、float型とcomplex 型を混合するタイプがほとんどないことがわかります。np.multiply
['??->?', 'bb->b', 'BB->B', 'hh->h', 'HH->H', 'ii->i', 'II->I', 'll->l', 'LL->L', 'qq->q', 'QQ->Q', 'ee->e', 'ff->f', 'dd->d', 'gg->g', 'FF->F', 'DD->D', 'GG->G', 'mq->m', 'qm->m', 'md->m', 'dm->m', 'OO->O']
"efdg"
"FDG"
機構的には、受け入れられた答えはもちろん正しいですが、私はより深い答えを与えることができると主張します。
まず、@ PeterCordesがコメントで行うように質問を明確にすることは有用です:「inf + 0jで機能する複素数の乗法的アイデンティティはありますか?」または言い換えると、OPが複雑な乗算のコンピュータ実装の弱点を認識している、または概念的に不健全なものがあるinf+0j
極座標を使用して、複雑な乗算をスケーリングと回転として見ることができます。1を掛けた場合のように、無限の「腕」を0度回転しても、有限の精度でその先端を配置することは期待できません。つまり、実際には、根本的に正しくないものがありますinf+0j
。つまり、無限大に到達するとすぐに、有限オフセットは無意味になります。
背景:この質問が関係する「大きなこと」は、数値のシステムを拡張することです(実数または複素数を考えてください)。これを実行したい理由の1つは、無限の概念を追加したり、たまたま数学者である場合に「コンパクト化」したりするためです。他にも理由があまりにも(、あるhttps://en.wikipedia.org/wiki/Galois_theory、https://en.wikipedia.org/wiki/Non-standard_analysis)が、我々は、こちらに興味を持っていません。
もちろん、そのような拡張について注意が必要なのは、これらの新しい数値を既存の計算に適合させたいということです。最も単純な方法は、無限に単一の要素(https://en.wikipedia.org/wiki/Alexandroff_extension)を追加し、ゼロで除算したもの以外のすべての要素と等しくすることです。これは実数(https://en.wikipedia.org/wiki/Projectively_extended_real_line)と複素数(https://en.wikipedia.org/wiki/Riemann_sphere)で機能します。
ワンポイントコンパクト化は単純で数学的には健全ですが、複数の無限を含む「より豊かな」拡張機能が求められてきました。実際の浮動小数点数のIEEE 754標準には、+ infと-infがあります(https://en.wikipedia.org/wiki/Extended_real_number_line)。自然で簡単なように見えますが、すでにフープを飛び越えてhttps://en.wikipedia.org/wiki/Signed_zeroのようなものを発明することを強制してい-0
ます
複合平面の1つ以上のinf拡張についてはどうですか?
コンピュータでは、複素数は通常、2つのfp実数を1つは実数部に、もう1つは虚数部に貼り付けることによって実装されます。すべてが有限である限り、それはまったく問題ありません。しかし、すぐに、無限が考慮されるようになると、物事はトリッキーになります。
複雑な平面には自然な回転対称性があり、平面全体をe ^ phijで乗算することはの周りのフィラジアン回転と同じであるため、複雑な計算とうまく結び付いてい0
ます。
さて、物事を単純に保つために、複雑なfpは、基礎となる実数実装の拡張(+/- inf、nanなど)を使用するだけです。この選択は非常に自然に見えるかもしれませんが、選択としては認識されていませんが、それが何を意味するかを詳しく見てみましょう。複雑な平面のこの拡張の単純な視覚化は次のようになります(I =無限、f =有限、0 = 0)
I IIIIIIIII I
I fffffffff I
I fffffffff I
I fffffffff I
I fffffffff I
I ffff0ffff I
I fffffffff I
I fffffffff I
I fffffffff I
I fffffffff I
I IIIIIIIII I
しかし、真の複素平面は複素乗算を尊重する平面であるため、より有益な予測は
III
I I
fffff
fffffff
fffffffff
I fffffffff I
I ffff0ffff I
I fffffffff I
fffffffff
fffffff
fffff
I I
III
この予測では、醜いだけでなく、OPの問題の根源でもある無限の「不均一な分布」が見られます。ほとんどの無限大(フォーム(+/- inf、finite)および(finite、+ / -inf)は4つの主要な方向にまとめられます。他のすべての方向は4つの無限大(+/- inf、+-inf)で表されます。複雑な乗算をこのジオメトリに拡張することは悪夢であることは驚くに値しません。 。
C99仕様のAnnex Gは、動作inf
とnan
相互作用のルールを曲げることを含め、それを機能させるために最善を尽くしています(本質的にinf
切り捨てnan
)。OPの問題は、実数と提案された純粋な虚数型を複素数に昇格しないことによって回避されますが、実数1と複素数1の動作が異なるからといって、解決策にはならないでしょう。はっきり言って、Annex Gは、2つの無限大の積がどうあるべきかを完全に指定するまでには至っていません。
無限のより良いジオメトリを選択することによって、これらの問題を試し、修正するのは魅力的です。拡張された実線と同様に、各方向に1つの無限大を追加できます。この構造は、射影平面に似ていますが、反対方向にまとめられません。無限大は極座標inf xe ^ {2 omega pi i}で表され、積の定義は簡単です。特に、OPの問題はかなり自然に解決されます。
しかし、ここで朗報が終わります。ある意味では、私たちのニュースタイルの無限大が実数部または虚数部を抽出する関数をサポートすることを要求することにより、不当にではなく---正方形1に戻すことができます。追加は別の問題です。角度を未定義に設定する必要がある2つの非正反対の無限大を追加しますnan
(つまり、角度は2つの入力角度の間にある必要があると主張できますが、「部分的な明るさ」を表す簡単な方法はありません)。
これらすべてを考慮すると、古き良き1点コンパクト化は、最も安全な方法です。多分、Annex Gの作者は、cproj
すべての無限をひとまとめにする関数を義務付けるときに同じことを感じました。
ここに、私よりも主題についてより有能な人々が回答する関連質問があります。
nan != nan
。私はこの答えが冗談だと理解していますが、それが書かれている方法でOPに役立つはずである理由がわかりません。
==
(そして、他の回答を受け入れた)ことを考えると、OPがタイトルを表現する方法の問題にすぎなかったようです。その矛盾を修正するために、タイトルを書き換えました。(私が@cmasterに同意するため、この回答の前半を意図的に無効にしています。それは、この質問が求めていることではありません)。
これは、CPythonでの複雑な乗算の実装方法の詳細です。他の言語(CやC ++など)とは異なり、CPythonはやや単純化したアプローチを取ります。
Py_complex
_Py_c_prod(Py_complex a, Py_complex b)
{
Py_complex r;
r.real = a.real*b.real - a.imag*b.imag;
r.imag = a.real*b.imag + a.imag*b.real;
return r;
}
上記のコードの1つの問題となるケースは次のとおりです。
(0.0+1.0*j)*(inf+inf*j) = (0.0*inf-1*inf)+(0.0*inf+1.0*inf)j
= nan + nan*j
しかし、-inf + inf*j
その結果として得たいと思います。
この点で、他の言語はそれほど進んでいません。複素数の乗算は長い間C標準の一部ではなく、C99にのみ付録Gとして含まれていました。これは、複雑な乗算の実行方法を説明しています。上記の学校の公式!C ++標準は複雑な乗算の動作を指定していないため、ほとんどのコンパイラー実装はC実装にフォールバックしています。C実装は、C99準拠(gcc、clang)かそうでない(MSVC)かです。
上記の「問題のある」例の場合、C99準拠の実装(学校の公式よりも複雑)は期待される結果をもたらします(ライブを参照)。
(0.0+1.0*j)*(inf+inf*j) = -inf + inf*j
C99標準を使用した場合でも、すべての入力に対して明確な結果が定義されているわけではなく、C99準拠のバージョンであっても異なる可能性があります。
別の副作用float
に昇格されていないcomplex
C99には掛けることであるinf+0.0j
と1.0
か、すること1.0+0.0j
(ここでライブを参照)異なる結果につながることができます:
(inf+0.0j)*1.0 = inf+0.0j
(inf+0.0j)*(1.0+0.0j) = inf-nanj
、虚部があること-nan
とないnan
(参照すべての静かなNaNのが等価であるので、ここでは役割を果たしていない(CPythonのためのような)これを)、さらにいくつかのそれらのは、符号ビットのセットを(持っているので、として印刷された「 - 」を参照してくださいこれを)とそうでないものもあります。これは少なくとも直感に反します。
私の重要なポイントは、「単純な」複素数の乗算(または除算)について単純なものは何もないことであり、言語やコンパイラを切り替える場合でも、微妙なバグや違いに備えなければなりません。
printf
、doubleでの動作と同様の動作の単なる実装の詳細です。「-」を出力するかどうか(nanであるかどうかに関係なく)を決定するために符号ビットを調べます。だからあなたは正しい、「ナン」と「-ナン」の間に意味のある違いはなく、答えのこの部分をすぐに修正します。
Pythonからの面白い定義。私たちはペンと紙でこれを解決している場合は、私が期待される結果をだろうと言うでしょうexpected: (inf + 0j)
、あなたが指摘したように、我々はの規範を意味することを知っているので、1
そうします(float('inf')+0j)*1 =should= ('inf'+0j)
:
しかし、あなたが見ることができるようにそれはそうではありません...それを実行すると、私たちは次のようになります:
>>> Complex( float('inf') , 0j ) * 1
result: (inf + nanj)
Pythonはこのことを理解し*1
、複素数のない規範として1
、それはとして解釈して*(1+0j)
、私たちがやろうとするとエラーが表示されるinf * 0j = nanj
ようinf*0
に解決することはできません。
あなたが実際にしたいこと(1が1の標準であると仮定):
場合、そのリコールz = x + iy
実部Xと虚部Yの複素共役複素数であるz
として定義されz* = x − iy
、その絶対値とも呼ばれるnorm of z
ように定義されます。
次のようなことをするの1
が標準であると仮定1
します。
>>> c_num = complex(float('inf'),0)
>>> value = 1
>>> realPart=(c_num.real)*value
>>> imagPart=(c_num.imag)*value
>>> complex(realPart,imagPart)
result: (inf+0j)
あまり直感的ではありませんが、コーディング言語は、日常的に使用されているものとは異なる方法で定義されることがあります。