Pythonにはそのような演算子-**
がありますが、JavaとC ++にはなぜないのか疑問に思いました。
演算子のオーバーロードを使用してC ++で定義するクラス用に1つ作成するのは簡単です(Javaでもそのようなことが可能だと思います)が、int、double、など、「Math.power
のようなライブラリ関数を使用する必要があります(通常は両方をdoubleにキャストする必要があります)。
つまり、このような演算子を定義しないのはなぜですか。プリミティブ型の場合は?
コメント
回答
一般的に、C(および拡張C ++)のプリミティブ演算子単純なハードウェアでほぼ1つの命令で実装できるように設計されています。べき乗のようなものは、しばしばソフトウェアサポートを必要とします。そのため、デフォルトでは存在しません。
また、言語の標準ライブラリによってstd::pow
の形式で提供されます。
最後に、整数データ型に対してこれを行うことはあまり意味がありません。指数のほとんどの小さな値でさえ、intに必要な範囲、つまり最大65,535を吹き飛ばすからです。確かに、doubleとfloatに対してこれを行うことはできますが、できません。 intsですが、めったに使用されない機能に対して言語に一貫性がないのはなぜですか?
コメント
- 私はこれのほとんどに同意しますが、モジュラスが浮動小数点型で演算子を使用できないことは、プリミティブデータ型では一貫性がありませんが、これもおそらく、現在普及していると思われるハードウェアでの単一の命令ではないでしょう。
- @Sion:少なくともx86、モジュラスは単一の命令です。(
DIV
は除算とモジュラスの両方を実行します)’は一貫性の点について説明しました。 - @Billy ONeal:浮動小数点modu単一の命令でlus? ‘最近、自分のことを知るためにアセンブリをいじくり回していません。 ‘の場合は、モジュラス演算子を浮動小数点型に適用できるようにする必要があります。
- @DonalFellows:FORTRANには、べき乗演算子があったずっと前にありました。 bignumサポートに似たもの。
- @DonalFellows:累乗演算子は’浮動小数点の場合ほど整数では役に立ちませんが、小さい累乗(特に2乗)では可能です。間違いなくその用途があります。個人的には、文字で演算子を作成するアプローチが好きです(Pascalが
div
で行うようにまたはFORTRANが.EQ.
で行うように)。言語の空白の規則によっては、予約語でなくても任意の数の演算子を使用できる場合があります。
回答
この質問はC ++で回答可能です:Stroustrup、「C ++の設計と進化」では、セクション11.6.1、pp。247-250でこれについて説明しています。
追加することには一般的な反対意見がありました。新しい演算子。すでに複雑すぎる優先順位テーブルに追加されます。ワーキンググループのメンバーは、機能を持っているよりも少しだけ便利だと考えており、時には自分の機能を代用できるようにしたいと考えていました。
オペレーターの候補はありませんでした。^
は排他的論理和であり、^^
は、&
との関係のために混乱を招きました|
および&&
および||
。 !
は、既存の値のべき乗のために!=
を書く傾向があるため、不適切でした。これはすでに採用されています。利用可能な最良のものは*^
であった可能性があり、これは明らかに誰も本当に好きではありませんでした。
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 ++に関する初期の不満の1つでした。
コメント
- いい答えです。 Javaはこの点でCを単純化しようとしたので、誰も新しい演算子を追加したくなかったと思います。 ‘誰も私に尋ねなかったのは残念ですが、
*^
が好きだったでしょう。 :D - Cは、テキストの書式設定を行うために構築されました。 Fortranは数学を行うために構築され、20年前に複雑な、パワーと行列の数学を持っていました。
- @Martin Beckett:Cがテキストフォーマット用に構築されたという証拠を見つけることができますか?そのための非常に不器用な言語のように思えます。Cの起源について’読んだところ、主にUnixのシステムプログラミング用に設計されたとのことです。
- @ DavidThornley-Unixを書き込むように設計されましたが、初期のUnixの使用はすべてテキスト形式であったようで、’の場合、広範な文字列とI / oライブラリ。
- +1:
a**p
の既存の意味はキラーです。 (その問題を回避するためのハック…Brr!)
回答
疑わしい em>それは、導入するすべての演算子が言語の複雑さを増すためです。したがって、参入障壁が非常に高くなります。指数を使用することはめったにありません。メソッド呼び出しを使用して満足しています。
コメント
- すべての機能は-100ポイントから始まります。
- ‘は
x**2
とx**3
を使用することはめったにありません。そして、コンパイラーが知っていて、単純なケースのために最適化する魔法の捕虜の実装がいいでしょう。 - @CodeInChaos:ただし、
x * x
とx * x * x
は’正方形と立方体の悪い代替品ではありません。 - @Davidできます’ xが式の場合は、単に
x*x
と記述します。最良の場合、コードは扱いにくくなり、最悪の場合、遅くなるか、さらには間違ってしまいます。したがって、’独自のSquare関数とCube関数を定義する必要があります。それでも、コードは**を電力演算子として使用するよりも醜いでしょう。 - @Davidかっこを使用する必要がありますが、’繰り返す必要はありません式が数回繰り返され、ソースコードが肥大化します。これにより、読みやすさが大幅に低下します。また、共通部分式除去は、コンパイラーが式に副作用がないことを保証できる場合にのみ可能です。そして、少なくとも.netジッターは’その点ではあまり賢くありません。
回答
Java言語とコアライブラリの設計者は、ほとんどの数学演算を数学クラスに任せることにしました。 Math.pow()を参照してください。
なぜですか?ビットごとの精度よりもパフォーマンスを優先する柔軟性。組み込みの数学演算子の動作はプラットフォームごとに異なる可能性があると言うのは言語仕様の残りの部分に反しますが、Mathクラスは、動作がパフォーマンスの精度を犠牲にする可能性があると具体的に述べているため、購入者は注意してください:
クラス StrictMath のいくつかの数値メソッドとは異なり、クラスの同等の関数のすべての実装数学は、ビットごとに同じ結果を返すように定義されていません。この緩和により、厳密な再現性が必要とされない、よりパフォーマンスの高い実装が可能になります。
回答
べき乗は、科学的なプログラミングを真っ向から狙っていたため、最初からFortranの一部でした。べき乗則の関係は物理学では一般的であるため、エンジニアや物理学者はシミュレーションで頻繁に使用します。
Pythonは、科学計算でも強力な存在感を示しています(NumPyやSciPyなど)。これは、べき乗演算子とともに、科学プログラミングも対象としていることを示しています。
C、Java、およびC#はシステムプログラミングにルーツがあります。おそらく、それはサポートされている演算子のグループから指数を除外した影響です。
単なる理論です。
回答
Cは、ALUでアクセス可能な一般的な算術演算に対してのみ演算子を定義しました。その主な目的は、アセンブリコードへの人間が読み取れるインターフェイスを作成することでした。
C ++は、すべてが必要だったため、演算子の動作を変更しませんでした。準拠するようにCで記述されたコードベース。
Javaは「既存のC ++プログラマーを威嚇したくないので、同じことをしました。
コメント
- Cが作成されたとき、乗算と除算はハードウェアで頻繁に不足することはなく、ソフトウェアで実装する必要がありました。それでも、Cには乗算と除算の演算子があります。
- @siride:私の知る限り、Unixを実行する最初のコンピューターであるPDP-7は、EAEを介してハードウェアの乗算と除算を行いました。参照: bitsavers.org/pdf/dec/pdp7/F-75_PDP-7userHbk_Jun65.pdf
回答
まあ、力に意味のあるすべての演算子がすでに使用されているからです。 ^はXORであり、**はポインターへのポインターを定義します。したがって、代わりに、同じことを行う関数があります。 (pow()のように)
コメント
- @ RTS-言語開発者は本当に効率以上の意味を探していますか?
- プログラミング言語の優れた開発者は両方を見ています。 ‘ Javaについては何も言えません。ただし、C ++では、pow()関数はコンパイル時に計算されます。また、通常の演算子と同じくらい効率的です。
- @RTS:定数畳み込みを実行できるコンパイラがない限り、
pow()
関数は実行時に計算を実行します。pow()
の場合、これは非常に疑わしいです。 (ただし、一部のコンパイラでは、プロセッサ組み込み関数を使用して計算を実行するオプションがあります。) - @In silico ‘最終的な計算を行うという意味ではありません。値、私はコンパイラが関数呼び出しを最適化することを意味したので、生の方程式があります。
- @josefx:確かに’正当な理由です。単一の
*
は、間接参照または乗算に使用される’に関係なく、字句トークンです。**
は、べき乗が1つまたは2つの字句トークンになることを意味し、’レクサーが記号をヒットする必要はありません。トークン化するテーブル。
回答
実際、算術演算子は関数のショートカットにすぎません。 (ほぼ)それらを使って行うことはすべて関数を使って行うことができます。例:
c = a + b; // equals c.set(a.add(b)); // or as free functions set(c, add(a,b));
もっと冗長なので、関数を使用して「パワー」を実行しても問題はありません。
答え
足し算/引き算/否定と掛け算/割り算は基本的な数学演算子です。力を演算子にするとしたら、どこで止めますか?平方根演算子?Nルート演算子?対数演算子?
作成者のことを話すことはできませんが、そのような演算子を言語に含めると扱いにくくなり、直交しなくなると思います。キーボードに残る非英数字/空白文字の数はかなり制限されています。現状では、C ++にモジュラス演算子があるのは不思議です。
コメント
- + 1- ‘演算子として
mod
を使用するのが奇妙な理由がわかりません。’ div id = “749f89ae7f”>
は通常、単一の命令です。’整数の基本演算です。’は、コンピュータサイエンスのあらゆる場所で最もよく使用されています。(mod
を使用せずに制限付きバッファーなどを実装すると悪臭を放ちます)
^
演算子の優先順位がべき乗の優先順位と一致しないため、問題はありません。式a + b ^ c
について考えてみます。数学では、最初にべき乗が実行され(b ^ c
)、次に結果のべき乗がa
に追加されます。 C ++では、加算は最初に実行され(a + b
)、次に^
演算子はc
。したがって、^
演算子を実装してべき乗を意味したとしても、優先順位はすべての人を驚かせます。^
はC ++のXORです。オーバーロードされた演算子は、プリミティブデータ型がそれを使用して行うことと同じである必要があることをお勧めします。++
演算子または!
演算子などをオーバーロードするC ++プログラマーの能力に真剣に疑問を投げかけます。 al。べき乗を意味します。ただし、’とにかくできません。これは、話している演算子が1つの引数しか受け入れないためです。べき乗には2つの引数が必要です。