为什么F#中的幂运算符仅适用于浮点数?

时间:2011-03-17 01:53:53

标签: f# language-design

我从未见过语言有指数或幂运算符只采用浮点数?

例如:

2 ** 2会抛出错误The type 'int' does not support any operators named 'Pow'

这个设计决定是否有正当理由?

4 个答案:

答案 0 :(得分:34)

(**)pown是两回事。当您看到(**)时,您可以使用对数来考虑数学公式。当你看到pown时,它只是一系列的乘法。我知道它起初可能令人惊讶/困惑,因为大多数其他语言没有产生这样的差异(主要是因为整数通常被隐式转换为浮点值)。即使在数学中,也存在一些小差异:参见Wikipedia entry,第一个定义仅适用于正整数指数。

由于它们是两种不同(但相关)的东西,它们有不同的签名。这是(**)

^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中的算法不同)。

我认为将这两个概念分开是一个很好的设计决定。

答案 1 :(得分:8)

对于整数幂,F#提供另一个运算符:pown。另外,作为附注,(**)pown都被重载,因此完全可以将它们与其他提供适当成员的类型一起使用(在{的情况下采用静态Pow方法在(**)的情况下,{1}}; (*)(/)运算符以及静态One属性。

我不能说为什么F#团队选择不在[{1}}上模拟pown成员,但也许他们认为这不是紧急因为Pow运营商可以改为使用(因为在大操作数的情况下,首先转换为float可能更有意义)。

答案 2 :(得分:2)

简短的回答是因为它对整数类型甚至int64s都不是很有用。 2 ^ 26只给你~1.84467441E19。因此,如果您有两个值X和Y都大于19,那么幂运算符将导致溢出。

我同意它对小值有用,但它通常对整数类型没用。

答案 3 :(得分:2)

F#所基于的语言是OCaml,它不执行运算符重载或自动数据强制(它们更喜欢显式强制)。

因此,即使添加双精度也需要不同的运算符(+。)。我不确定这是否是F#确定的严格程度,但我猜它是。

在像Python或Scheme这样的动态语言中,如果数字太大,你会自动将数据强制转换为更大的数据存储。例如,您可以使用整数指数的整数为结果提供一个大整数。

OCaml和F#具有极端类型安全的精神。