算术运算符
本主题介绍 F# 中提供的算术运算符。
二元算术运算符摘要
F# 中的算术运算可以采用以下两种模式来执行:未检查和检查。 默认情况下,算术运算使用未检查的行为,该行为优先考虑性能,但允许溢出/下溢。 在这种情况下,检查的运算符通过引发异常来优先保证安全性。
未检查的算术运算符
下表总结了可对已取消装箱的整数和浮点类型进行未检查的算术运算的二进制算术运算符。
二元运算符 | 备注 |
---|---|
+ (加法,加) |
取消选中。 当数字加在一起并且总和超过类型支持的最大绝对值时,可能溢出条件。 |
- (减法,减) |
取消选中。 当提取无符号类型或浮点值太小而不能由类型表示时,可能出现下溢情况。 |
* (乘法,乘以) |
取消选中。 当数字相乘且产品超过类型支持的最大绝对值时,可能的溢出条件。 |
/ (除法,除以) |
对于整型类型,以零作除数会导致 DivideByZeroException。 对于浮点类型,除以零可提供特殊的浮点值 infinity 或 -infinity 。 当浮点数太小,无法由类型表示时,也可能存在下溢条件。 |
% (余数,求余) |
返回除法运算的余数。 结果的符号与第一个操作数的符号相同。 |
** (乘方,求幂) |
当结果超过类型的最大绝对值时,可能的溢出条件。 指数运算符仅适用于浮点类型。 |
当发生溢出或下溢时,未检查的行为不会引发异常,因此在对大值或极值进行算术运算时,其安全性较低。
检查的算术运算符
下表总结了可对已取消装箱的整数和浮点类型进行检查的算术运算的二进制算术运算符。 已检验的运算符确保计算经过验证以防止出现溢出或下溢,从而为关键应用程序提供更安全的算术运算。
二元运算符 | 备注 |
---|---|
+ (加法,加) |
如果结果超过最大值或低于类型支持的最小值,则引发 OverflowException。 溢出和下溢都有可能发生。 |
- (减法,减) |
如果结果超过最大值或低于类型支持的最小值,则引发 OverflowException。 溢出和下溢都有可能发生。 |
* (乘法,乘以) |
如果产品超出最大值或低于类型支持的最小值,则引发 OverflowException。 溢出和下溢都有可能发生。 |
检查的运算符对于确保明确捕获和处理算术溢出很有用。
下面是一个示例:
open Microsoft.FSharp.Core.Operators.Checked
let safeAddition () =
try
let result = 2147483647 + 1 // Attempt to add integers at their maximum boundary
printfn "Result: %d" result
with
| :? System.OverflowException as ex ->
printfn "Overflow occurred: %s" ex.Message
safeAddition()
// Output:
// Overflow occurred: Arithmetic operation resulted in an overflow.
在检查和未检查的运算符之间进行选择
检查的运算符:非常适合必须显式检测和处理溢出错误的场合。
未检查的运算符:默认情况下,F# 会出于性能原因而使用未检查的算术运算。 当发生溢出或下溢时,这些操作可能会以无提示方式生成不正确的结果。 请谨慎使用。
一元算术运算符摘要
下表汇总了可用于整型和浮点类型的一元算术运算符。
一元运算符 | 备注 |
---|---|
+ (正) |
可应用于任何算术表达式。 不会更改值的符号。 |
- (求反,负) |
可应用于任何算术表达式。 更改值的符号。 |
整数类型的溢出或下溢行为是回绕。 这会导致结果不正确。 整数溢出是一个可能导致安全问题的严重潜在问题,尤其是在编写软件时没有考虑到这一点的时候。 如果这是你的应用程序需要关注的问题,请考虑使用 Microsoft.FSharp.Core.Operators.Checked
中的选中运算符。
二进制比较运算符摘要
下表显示了可用于整型和浮点类型的二进制比较运算符。 这些运算符返回类型为 bool
的值。
对于相等性,永远不应直接比较浮点数,因为 IEEE 浮点表示形式不支持完全相等运算。 可以通过检查代码轻松验证是否相等的两个数字实际上可能具有不同的位表示。
操作员 | 备注 |
---|---|
= (相等,等于) |
这不是赋值运算符。 它仅用于比较。 这是一个泛型运算符。 |
> (大于) |
这是一个泛型运算符。 |
< (小于) |
这是一个泛型运算符。 |
>= (大于或等于) |
这是一个泛型运算符。 |
<= (小于或等于) |
这是一个泛型运算符。 |
<> (不等于) |
这是一个泛型运算符。 |
重载和泛型运算符
本主题中讨论的所有运算符均在 Microsoft.FSharp.Core.Operators 命名空间中定义。 某些运算符是使用静态解析的类型参数定义的。 这意味着与该运算符一起使用的每种特定类型都有单独的定义。 所有一元和二元算术和按位运算符都属于此类别。 比较运算符是泛型运算符,因此适用于任何类型,而不仅仅是基元算术类型。 可区分的联合和记录类型具有它们自己的自定义实现,这些实现由 F# 编译器生成。 类类型使用方法 Equals。
泛型运算符是可自定义的。 要自定义比较函数,请重写 Equals 以提供你自己的自定义相等比较,然后实现 IComparable。 System.IComparable 接口具有单个方法,即 CompareTo 方法。
运算符和类型推理
表达式中运算符的使用约束该运算符的类型推理。 此外,使用运算符可防止自动通用化,因为使用运算符意味着算术类型。 如果没有任何其他信息,F# 编译器将 int
推断为算术表达式的类型。 可以通过指定另一种类型来替代此行为。 因此,以下代码中的参数类型和返回类型的 function1
被推断为 int
,但 function2
的类型被推断为 float
。
// x, y and return value inferred to be int
// function1: int -> int -> int
let function1 x y = x + y
// x, y and return value inferred to be float
// function2: float -> float -> float
let function2 (x: float) y = x + y