Подтвердить что ты не робот

Почему оператор мощности в F # работает только для чисел с плавающей запятой?

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

Например:

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

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

4b9b3361

Ответ 1

(**) и 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).

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

Ответ 2

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

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

Ответ 3

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

Я согласен, что это полезно при малых значениях, однако оно не является полезным для целых типов.

Ответ 4

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

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

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

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