Java / C ++にパワー演算子がないのはなぜですか?


23

そのような演算子がありますが**、Pythonでは、なぜJavaとC ++にも演算子がないのかと思っていました。

演算子のオーバーロードを使用してC ++で定義するクラスに簡単に作成できます(Javaでもこのようなことが可能だと思います)が、int、doubleなどのプリミティブ型について話すときは、ライブラリを使用する必要がありますのような関数Math.power(通常、両方をdoubleにキャストする必要があります)。

だから-なぜプリミティブ型にそのような演算子を定義しないのですか?


8
C ++では、独自の演算子を作成できません。既存の演算子のみをオーバーロードできます。

1
@Maheshなので、独自のNumberクラスを作成し、^演算子をオーバーロードしてパワーにすることができます。それは本当にありません。

22
@RanZilber:^演算子の優先順位がべき乗の優先順位と一致しないため、問題になります。式を考えてくださいa + b ^ c。数学では、べき乗が最初に実行され(b ^ c)、結果の累乗がに追加されaます。C ++では、最初に加算が実行され(a + b)、次に^演算子がで実行されcます。その^ため、べき乗を意味する演算子を実装した場合でも、優先順位はすべての人を驚かせるでしょう。
インシリコ

2
@RamZilber- ^C ++のXORです。オーバーロードされた演算子は、プリミティブデータ型がそれを使用して行うことと何も変わらないようにすることをお勧めします。

4
@RanZilber:指数関数を意味するために言及したこれらの演算子のいずれかを使用することは、まったく直感的ではないためです。++演算子または!演算子et をオーバーロードするC ++プログラマーの能力に真剣に疑問を呈します。等 べき乗を意味します。しかし、とにかくすることはできません。なぜなら、あなたが話す演算子は引数を1つしか受け入れないからです。べき乗には2つの引数が必要です。
インシリコ

回答:


32

一般的に、Cのプリミティブ演算子(および拡張C ++による)は、おおよそ1つの命令で単純なハードウェアによって実装できるように設計されています。べき乗のようなものは、しばしばソフトウェアのサポートを必要とします。そのため、デフォルトでは存在しません。

また、言語の標準ライブラリによっての形式で提供されstd::powます。

最後に、整数データ型に対してこれを行うことはあまり意味がありません。なぜなら、べき乗の小さな値でさえ、intに必要な範囲(最大65,535)を吹き飛ばすからです。確かに、倍精度浮動小数点数に対してこれを行うことはできますが、intに対してはできませんが、めったに使用されない機能に対して言語を矛盾させるのはなぜですか?


4
私はこれの大部分に同意しますが、モジュラス演算子が浮動小数点型で使用できないという事実はプリミティブデータ型では一貫性がありませんが、それはおそらく私が想像するどのハードウェアでも単一の命令ではないでしょう。

@Sion:少なくともx86では、モジュラスは単一の命令です。(DIV除算とモジュラスの両方を行います)あなたは一貫性の点で私を得ています
ビリーONeal

@Billy ONeal:単一命令での浮動小数点モジュラス?私は自分の知っているように、最近アセンブリの中でいじくり回していません。その場合は、モジュラス演算子を浮動小数点型に適用できるようにする必要があります。

3
@DonalFellows:FORTRANには、bignumサポートに似たものが登場するずっと前に、べき乗演算子がありました。
supercat

1
@DonalFellows:べき乗演算子は、整数では浮動小数点数ほど有用ではありませんが、小さい指数(特に2乗)では間違いなく使用できます。個人的には、演算子を文字で構成するアプローチが好きです(Pascalがで、divまたはFORTRANで.EQ.)言語の空白ルールに応じて、予約語である必要なく、任意の数の演算子を使用できる場合があります。
supercat

41

この質問にはC ++の答えがあります。Stroustrupの「C ++の設計と進化」では、セクション11.6.1、pp。247-250でこれについて説明しています。

新しい演算子の追加には一般的な反対がありました。すでに複雑すぎる優先順位テーブルに追加されます。ワーキンググループのメンバーは、機能を持っていることよりもほんの少しの便利さしか与えないだろうと考え、時々自分の機能を代用できるようにしたかった。

オペレーターに適した候補者はいませんでした。 ^は排他的^^論理和であり、&and |&&andの関係により混乱を招き||ます。 既存の値のべき乗!を記述する自然な傾向があるため、これは不適切!=でした。それはすでに採用されていました。利用可能な最高のものは*^、おそらく誰も本当に好きではなかったかもしれません。

Stroustrupは**再び検討されましたが、C:にa**pはすでに意味があり、それ はa何をp指しているかを示し、へのポインターとしてchar ** c;宣言しcていますchar**「ポインタへのポインタの宣言」、「次のものが指すものの時間」(ポインタの場合)、または「べき乗」(数字が続く場合)を意味するトークンとして導入すると、優先順位の問題が発生しました。 pが数値であるかのa/b**pように解析するa/(b**p)必要(a/b) * *pがありますが、pがポインターである場合、パーサーでこれを解決する必要があります。

つまり、それは可能でしたが、優先順位テーブルとパーサーが複雑になり、両方ともすでに複雑すぎます。

Javaの話は知りません。私ができることはすべて推測することです。それは始まっC、については、すべてのC演算子は、簡単に、一部のコンパイラを簡素化するために、一部の単純なオペレーターに時間のかかる機能を隠すことを避けるために、アセンブリコードに変換されます(事実operator+()他の人が非常に複雑とパフォーマンスヒットを隠す可能性があり、一でしたC ++についての初期の苦情)。


2
いい答えだ。Javaはこの点でCを単純化しようとしたので、だれも新しい演算子を追加したくなかったと思います。それは誰も私に尋ねなかったのは残念だ、私は確かに好きだっ*^ただろう。:D
maaartinus

1
Cは、テキストの書式設定を行うために構築されました。Fortranは数学を実行するために構築されており、20年前に複雑でパワーと行列の数学がありました。
マーティンベケット

@Martin Beckett:テキストの書式設定のためにCが構築されたという証拠を見つけることができますか?それは私にとって非常に不器用な言語のようで、Cの起源について読んだことから、主にUnixのシステムプログラミング用に設計されたと言われています。
デビッドソーンリー

@DavidThornley-Unixを記述するように設計されましたが、初期のUnixでの使用はすべてテキストの書式設定であったようです。
マーティンベケット

6
+1:の既存の意味a**pはキラーです。(その問題を回避するためのハッキング…Brr!)
ドナルフェローズ

13

あなたが紹介するすべての演算子が言語の複雑さを増すからだと思う。したがって、参入障壁は非常に高い。べき乗を使用することは非常にまれであり、メソッド呼び出しを使用してそれを行うことができてうれしいです。



3
使用することはめったにx**2ありx**3ません。そして、コンパイラーが知っており、単純なケース用に最適化する魔法のパウの実装がいいでしょう。
CodesInChaos

2
@CodeInChaos:ただしx * xx * x * x広場とキューブの悪い代用品ではありません。
デビッドソーンリー

5
@David x*xは、xが式の場合、単純に書くことはできません。最良の場合、コードは扱いにくくなり、最悪の場合は遅くなるか、さらには間違ってしまいます。そのため、独自のSquare関数とCube関数を定義する必要があります。そしてその場合でも、コードは**をパワー演算子として使用するよりもthanいでしょう。
-CodesInChaos

1
@Davidはい、括弧を付ける必要がありますが、式を数回繰り返してソースコードを肥大化する必要はありません。これにより、読みやすさが大幅に低下します。また、一般的な副次式の除去は、コンパイラが式に副作用がないことを保証できる場合にのみ可能です。そして、少なくとも.netジッターはその点ではあまり賢くありません。
-CodesInChaos

11

Java言語とコアライブラリの設計者は、ほとんどの数学演算をMathクラスに委ねることに決めました。Math.pow()を参照してください。

どうして?ビット単位の精度よりもパフォーマンスを優先する柔軟性。組み込みの数学演算子の動作はプラットフォームごとに異なる可能性があると言うのは、言語仕様の残りの部分に反しますが、Mathクラスでは、動作がパフォーマンスの精度を犠牲にする可能性があると明確に述べているため、購入者は注意してください:

クラスStrictMathの一部の数値メソッドとは異なり、クラスMathの同等の関数のすべての実装は、ビットごとに同じ結果を返すように定義されていません。この緩和により、厳密な再現性が要求されない、より優れたパフォーマンスの実装が可能になります。


6

指数関数は、科学プログラミングを真正面から狙っていたため、最初からFortranの一部でした。べき乗則の関係は物理学では一般的であるため、エンジニアや物理学者はシミュレーションでよく使用します。

Pythonは科学コンピューティングでも強力な存在感を示しています(NumPyやSciPyなど)。それは、そのべき乗演算子とともに、科学プログラミングも目的としたことを示唆しています。

C、Java、およびC#は、システムプログラミングにルーツを持っています。おそらく、それは、サポートされている演算子のグループからべき乗を排除した影響です。

ただの理論。


4

Cは、ALUでアクセス可能な一般的な算術演算の演算子のみを定義しました。その主な目的は、アセンブリコードへの人間が読めるインターフェイスを作成することでした。

C ++は、Cで記述されたすべてのコードベースを準拠させたいため、演算子の動作を変更しませんでした。

Javaは、既存のC ++プログラマを脅迫したくないため、同じことをしました。


Cが作成されたとき、乗算と除算はめったにハードウェアに欠けていなかったため、ソフトウェアで実装する必要がありました。しかし、Cには乗算演算子と除算演算子があります。
-siride

@siride:私の知る限り、Unixを実行した最初のコンピューターであるPDP-7には、EAEを介したハードウェアの乗算と除算がありました。参照してください:bitsavers.org/pdf/dec/pdp7/F-75_PDP-7userHbk_Jun65.pdf
Tugrul Ates

1

それは、権力にとって意味のあるすべてのオペレーターがすでに使用されているからです。^はXORで、**はポインターへのポインターを定義します。そのため、代わりに同じことを行う関数のみがあります。(pow()など)


@RTS-言語開発者は効率よりも感覚を本当に探していますか?

プログラミング言語の優れた開発者は両方を検討します。Javaについては何も言えません。ただし、c ++では、pow()関数はコンパイル時に計算されます。そして、通常のオペレーターと同じくらい効率的です。

@RTS:のpow()ためpow()に定数の折りたたみを行うことができるコンパイラーを入手しない限り、関数は実行時に計算を実行します。(ただし、一部のコンパイラは、プロセッサ組み込み関数を使用して計算を実行するオプションを提供します。)
In silico

@In silico最終的な値を計算することを意味するのではなく、コンパイラーが関数呼び出しを最適化することを意味したので、生の方程式が得られます。

2
@josefx:確かな理由です。*間接または乗算に使用されるかどうかに関係なく、シングルは字句トークンです。**つまり、べき乗は、1つまたは2つの字句となり、あなたは本当にあなたのレクサーがトークン化するシンボルテーブルをヒットする必要がありますする必要はありません。
デビッドソーンリー

0

事実、算術演算子は関数のショートカットにすぎません。(ほぼ)それらを使用して行うことはすべて、関数を使用して実行できます。例:

c = a + b;
// equals
c.set(a.add(b));
// or as free functions
set(c, add(a,b));

これはより冗長なため、関数を使用して「の力」を実行しても何も問題はありません。


-1

加算/減算/否定と乗算/除算は、基本的な数学演算子です。電源をオペレータにする場合、どこで停止しますか?平方根演算子?Nルート演算子?対数演算子?

私は彼らのクリエイターのために話すことはできませんが、そのような演算子を言語に含めることは扱いにくく、直交しないと思うと言えます。キーボードに残っている非英数字/空白文字の数はかなり制限されています。現状では、C ++にモジュラス演算子があるのは奇妙です。


+1- mod演算子として持つことが奇妙な理由がわからない。通常は単一の命令です。これは整数に対する原始的な操作です。これは、コンピューターサイエンスのあらゆる場所で使用されています。(mod
バウンド

@Billy ONeal:整数型と浮動小数点型で使用できることの間に矛盾があるため、奇妙です。絶対に便利ですが、私はそれを削除することを夢見ていません。ただ風変わりです。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.