我从未见过语言有指数或幂运算符只采用浮点数?
例如:
2 ** 2
会抛出错误The type 'int' does not support any operators named 'Pow'
这个设计决定是否有正当理由?
答案 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#具有极端类型安全的精神。