言語に浮動小数点数のみをとる指数またはべき乗演算子があるのを見たことがありませんか?
例えば:
2 ** 2
エラーをスローしますThe type 'int' does not support any operators named 'Pow'
この設計上の決定には正当な理由がありますか?
(**)
とpown
は2つの異なるものです。 (**)
が表示されている場合は、対数を使用して数式を考えることができます。 pown
が表示されている場合、それは単なる一連の乗算です。他のほとんどの言語ではそのような違いがないため(主に整数が暗黙的に浮動小数点値に変換されることが多いため)、最初は驚くべき/混乱する可能性があることを理解しています。数学でも、小さな違いがあります。 Wikipediaエントリ を参照してください。最初の定義は、正の整数の指数に対してのみ機能します。
それらは2つの異なる(しかし関連する)ものであるため、異なる署名を持っています。これが(**)
です:
^a -> ( ^b -> ^a) when ^a : (static member Pow : ^a * ^b -> ^a)
そしてここにpown
があります:
^a -> (int -> ^a)
when ^a : (static member get_One : -> ^a) and
^a : (static member ( * ) : ^a * ^a -> ^a) and
^a : (static member ( / ) : ^a * ^a -> ^a)
独自のタイプを作成する場合、One
で機能させるには、pown
、(*)
、および(/)
があれば十分です。ライブラリがループを実行します(最適化されており、単純なO(n)ではありません)。
非整数値の型で(**)
演算子を使用する場合は、完全なロジックを作成する必要があります(また、pown
と同じアルゴリズムではありません)。
2つの概念を分離することは良い設計上の決定だったと思います。
整数乗の場合、F#は別の演算子pown
を提供します。また、補足として、(**)
とpown
の両方がオーバーロードされているため、適切なメンバーを提供する他のタイプ(この場合は静的Pow
メソッド)でそれらを使用することは完全に可能です。 (**)
; (*)
および(/)
演算子と、One
の場合は静的pown
プロパティ。
F#チームがPow
のint
メンバーをシミュレートしないことを選択した理由については話せませんが、pown
オペレーターができるため、緊急性を感じなかったのかもしれません。代わりに使用されます(そして、大きなオペランドの場合、最初にfloatに変換する方がおそらく理にかなっているため)。
簡単な答えは、int64であっても、整数型にはあまり役に立たないためです。 2 ^ 26では〜1.84467441E19しか得られません。したがって、2つの値XとYの両方がたとえば19より大きい場合、電力演算子はオーバーフローになります。
私はそれが小さな値に役立つことに同意しますが、一般的に整数型には役立ちません。
F#のベースとなる言語はOCamlであり、演算子のオーバーロードや自動データ強制を行いません(明示的な強制を好みます)。
したがって、doubleを追加する場合でも、別の演算子(+。)が必要です。これがF#が確実に厳格になる場所であるかどうかはわかりませんが、そうだと思います。
PythonやSchemeのような動的言語では、数値が大きすぎると、より大きなデータストレージに自動的にデータを強制変換されます。たとえば、整数の指数を持つ整数を使用して、結果。
OCamlとF#は極端な型安全性の精神を持っています。