Почему оператор мощности в F # работает только для чисел с плавающей запятой? - PullRequest
56 голосов
/ 17 марта 2011

Я никогда не видел, чтобы в языке экспонента или оператор степени брал только числа с плавающей запятой?

Например:

2 ** 2 выдает ошибку The type 'int' does not support any operators named 'Pow'

Есть ли веские причины для такого решения?

Ответы [ 4 ]

35 голосов
/ 23 марта 2011

(**) и pown - это две разные вещи. Когда вы видите (**), вы можете думать о математической формуле, используя логарифмы. Когда вы видите pown, это просто серия умножений. Я понимаю, что поначалу это может удивлять / сбивать с толку, потому что большинство других языков не имеют такой разницы (в основном потому, что целые числа часто неявно преобразуются в значения с плавающей запятой). Даже в математике есть небольшая разница: см. Запись Википедии , первое определение работает только для положительных целочисленных показателей.

Поскольку это две разные (но связанные) вещи, они имеют разные подписи. Вот (**):

^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).

Я думаю, это было хорошее дизайнерское решение, чтобы разделить две концепции.

9 голосов
/ 17 марта 2011

Для интегральных степеней F # предоставляет другого оператора: pown.Кроме того, как примечание, оба (**) и pown перегружены, так что вполне возможно использовать их с другими типами, которые предоставляют соответствующие члены (статический метод Pow в случае (**); (*)и (/) операторы и статическое One свойство в случае pown).

Я не могу сказать, почему команда F # решила не моделировать Pow член на int, но, возможно, они не чувствовали, что это было срочно, поскольку вместо этого можно было бы использовать оператор pown (и, поскольку в случае больших операндов, вероятно, имеет смысл преобразовать его в float первым).

2 голосов
/ 17 марта 2011

Язык, на котором основан F #, это OCaml, который не выполняет перегрузку операторов или автоматическое приведение данных (они предпочитают явное приведение).

Таким образом, даже для добавления двойников требуется другой оператор (+.). Я не уверен, что именно здесь F # определенно проявляет свою строгость, но я предполагаю, что это так.

В динамических языках, таких как Python или Scheme, вы бы автоматически приводили данные к большему хранилищу данных, если их число было слишком большим. Например, у вас могут быть целые числа с целочисленными показателями, дающие большое целое число для результата.

OCaml и F # обладают духом экстремальной безопасности типов.

2 голосов
/ 17 марта 2011

Короткий ответ: потому что он не очень полезен для целочисленных типов, даже для int64. 2 ^ 26 дает вам ~ 1.84467441E19. Таким образом, если у вас было два значения X и Y, каждое из которых больше, чем, скажем, 19, то оператор power приведет к переполнению.

Я согласен, что это полезно для небольших значений, но обычно это не полезно для целочисленных типов.

...