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

unj*_*nj2 58 f# language-design

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

例如:

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

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

Lau*_*ent 35

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

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

^a -> ( ^b ->  ^a) when  ^a : (static member Pow :  ^a *  ^b ->  ^a)
Run Code Online (Sandbox Code Playgroud)

这是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)
Run Code Online (Sandbox Code Playgroud)

如果你创建自己的类型,你只需要拥有你One,(*)(/)得到它一起工作pown.库将为您完成循环(它已经过优化,它不是天真的O(n)).

如果要(**)在类型上使用运算符作为非整数值,则必须编写完整逻辑(并且它与算法不同pown).

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


kvb*_*kvb 9

对于整数幂,F#提供另一个运算符:pown.此外,作为一个方面说明,两者(**)pown过载,所以这是完全可能的与其它类型的,其提供适当的部件(一个静态使用它们Pow中的情况下,方法(**); (*)以及(/)运营商和静态One中的情况下,属性pown).

我不能说为什么F#团队选择不模拟Pow成员int,但也许他们觉得不紧急,因为pown可以使用运算符(并且因为它可能更有意义转换为浮点数在大操作数的情况).

  • 实际上,`**`有签名`^ a - > ^ b - > ^ a当^ a :(静态成员Pow:^ a*^ b - > ^ a)`,所以`3I**1000`,` 3.0f**3.2f`和`3.0**3.2`都是有效的. (3认同)

Chr*_*ith 2

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

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