Pythonにはそのような演算子-**
がありますが、JavaおよびC++にも演算子がないのはなぜですか?.
演算子のオーバーロードを使用してC++で定義するクラス用に作成するのは簡単です(そして、Javaでもそのようなことが可能だと思います)が、int、doubleなどのプリミティブ型について話すときは、ライブラリを使用する必要がありますMath.power
のような関数(通常、両方をdoubleにキャストする必要があります)。
それで、なぜプリミティブ型に対してそのような演算子を定義しないのですか?
一般的に言えば、Cのプリミティブ演算子(およびC++の拡張)は、単純なハードウェアでほぼ単一の命令で実装できるように設計されています。指数化のようなものは、しばしばソフトウェアのサポートを必要とします。したがって、デフォルトではありません。
また、言語の標準ライブラリによってstd::pow
の形式で提供されます。
最後に、整数データ型に対してこれを行うのはあまり意味がありません。指数化のほとんどの小さい値でさえ、intに必要な範囲(最大65,535)を吹き飛ばすためです。確かに、これはdoubleとfloatに対しては可能ですが、intに対してはできませんが、まれに使用される機能について言語を一貫性のないものにするのはなぜですか?
この質問は、C++に対して回答可能です。Stroustrup、「C++の設計と進化」では、これについてセクション11.6.1の247〜250ページで説明しています。
新しい演算子を追加することに一般的な反対がありました。すでに複雑すぎる優先テーブルに追加されます。ワーキンググループのメンバーは、機能を持つことはあまり便利ではないと考え、彼らは時々自分の機能を代用できるようにしたいと考えました。
オペレーターにふさわしい候補者はいませんでした。 ^
は排他的論理和であり、^^
と&
および|
と&&
の間の関係のため、||
は混乱を招きました。 !
は、既存の値の累乗のために!=
を書く自然な傾向があり、すでに採用されているため、不適切でした。入手可能な最良のものは*^
である可能性があります。
Stroustrupは再び**
を検討しましたが、Cではすでに意味があります。a**p
はa
が指すp
倍であり、char ** c;
はc
をchar
へのポインターへのポインターとして宣言します。 **
を「ポインタへのポインタの宣言」、「次のものが指す時間」(ポインタの場合)、または「指数」(その後に数値が続く)を意味するトークンとして導入すると、優先順位の問題が発生しました。 a/b**p
は、pが数値の場合はa/(b**p)
として解析する必要がありますが、pがポインタの場合は(a/b) * *p
であるため、パーサーで解決する必要があります。
つまり、それは可能でしたが、優先順位テーブルとパーサーが複雑になり、どちらもすでに複雑すぎました。
Javaについての話は知りません。私ができることはすべて推測です。 Cについては、それが始まった時点で、すべてのC演算子はアセンブリコードに簡単に変換されます。これは、一部はコンパイラを簡素化し、一部は単純な演算子で時間のかかる機能を非表示にすることを回避します(operator+()
などが非表示にできるという事実)大きな複雑さとパフォーマンスへの影響は、C++に関する初期の不満の1つでした。
I 容疑者これは、導入するすべての演算子が言語の複雑さを増すためです。したがって、参入障壁は非常に高いです。私は非常にまれに指数を使用していることに気づきました。そして、メソッドコールを使用して満足しています。
Java言語およびコアライブラリの設計者は、ほとんどの数学演算を Math クラスに委任することを決定しました。- Math.pow() を参照してください。
どうして?ビットごとの精度よりもパフォーマンスを優先する柔軟性。組み込みの数学演算子の動作はプラットフォームごとに異なる可能性があると言うことは、言語仕様の残りの部分に反することになりますが、Mathクラスは特に動作がパフォーマンスの精度を犠牲にする可能性があると述べているため、購入者は注意してください。
クラス StrictMath の数値メソッドの一部とは異なり、Mathクラスの同等の関数のすべての実装は、ビットごとに同じ結果を返すように定義されていません。この緩和により、厳密な再現性を必要としない、より優れたパフォーマンスの実装が可能になります。
指数演算は、科学的プログラミングを目的としたものであるため、最初からFortranの一部でした。べき法則の関係は物理学では一般的であるため、エンジニアや物理学者はシミュレーションでよく使用します。
Pythonは科学計算でも強力な存在です(例:NumPyおよびSciPy)。それは、その指数演算子とともに、それも科学的プログラミングを目的としていたことを示唆しています。
C、Java、C#はシステムプログラミングにルーツがあります。おそらくそれは、サポートされている演算子のグループに累乗を含ませなかった影響です。
単なる理論。
Cは、ALUでアクセス可能な一般的な算術演算の演算子のみを定義しました。その主な目的は、アセンブリコードへの人間が読めるインターフェイスを作成することでした。
C++は、Cで記述されたすべてのコードベースを準拠させる必要があるため、演算子の動作を変更しませんでした。
既存のC++プログラマーを脅迫したくなかったので、Javaも同じことをしました。
まあ、パワーに意味のあるすべてのオペレーターがすでに使用されているからです。 ^はXORであり、**はポインタへのポインタを定義します。そのため、代わりに同じことを行う関数を持っています(pow()など)。
実際、算術演算子は関数のショートカットにすぎません。 (ほぼ)関数を使用して、それらを使用して実行できるすべての操作を実行できます。例:
c = a + b;
// equals
c.set(a.add(b));
// or as free functions
set(c, add(a,b));
それはもっと冗長なので、関数を使用して「パワー」を実行することに何の問題もありません。