Fortran数值变量的精度


`Fortran`提供了两种基本的数值变量类型:整型(`integer`)和实型(`real`)。整型变量只能表示整数,而实型变量可以表示小数。整型变量有一个默认的种类(`kind`),通常是4,表示它们占用32位(4字节)的内存空间。实型变量有两个默认的种类,分别是4和8,表示它们占用32位或64位(8字节)的内存空间。这两个种类分别对应于单精度(`real`)和双精度(`double precision`)实型变量。
除了默认的种类,Fortran还允许用户自定义数值变量的种类,以满足不同的精度和范围需求。用户可以使用`kind`属性来指定一个数值变量的种类,例如:
```Fortran
integer, kind = 2 :: i, j, k ! 16-bit integers
real, kind = 16 :: x, y, z ! 128-bit reals
```
用户也可以使用`selected_int_kind`和`selected_real_kind`这两个内置函数来获取所需精度和范围的种类参数值。这两个函数都接受一个或两个整数参数,并返回一个整数,表示满足条件的最小种类值。如果没有满足条件的种类,则返回`-1`。例如:
```fortran
integer :: k1, k2, k3, k4
k1 = selected_int_kind(4) ! returns the kind value for at least 4 decimal digits
k2 = selected_real_kind(6) ! returns the kind value for at least 6 decimal digits of precision
k3 = selected_real_kind(10, 100) ! returns the kind value for at least 10 decimal digits of precision and a range of at least 10^(-100) to 10^(100)
k4 = selected_real_kind(20, 1000) ! returns -1, as no such kind is available
```
Fortran还提供了一些内置函数来查询数值变量的精度和范围信息。这些函数包括:
`bit_size(i)`: 返回一个整型变量`i`占用的比特数。
`precision(x)`: 返回一个实型变量`x`的小数位精度。
`range(x)`: 返回一个实型变量`x`的十进制指数范围。
`maxexponent(x)`: 返回一个实型变量`x`能够表示的最大正指数。
`minexponent(x)`: 返回一个实型变量`x`能够表示的最小负指数。
`radix(x)`: 返回一个实型变量`x`使用的基数(通常是2)。
`digits(x)`: 返回一个实型变量`x`使用的有效数字位数。
## 注意事项
- 这些函数都返回整数值,因此需要用整型变量或常量来接收它们的返回值。
- 这些函数都是依赖于机器和编译器的,因此在不同的平台上可能会得到不同的结果。
- 这些函数都是针对单个变量或常量的,而不是针对类型或种类的。因此,如果想要查询某个类型或种类的精度或范围信息,需要先定义一个该类型或种类的变量或常量,然后将其作为参数传递给这些函数。
## 通用数学函数
通用数学函数是指那些可以接受不同种类(`kind`)的实型或复型参数,并根据参数的种类返回相应种类的结果的函数。例如,`sin(x)`函数可以接受单精度或双精度的实型参数,并返回相同精度的实型结果。通用数学函数是`Fortran`语言的内置函数,不需要声明或引用外部库。
使用通用数学函数的优点是可以简化代码的编写和维护,不需要为不同精度的参数编写不同的函数。但是,使用通用数学函数也有一些注意事项,以保证数值精度的一致性:
### 结果的精度
通用数学函数的结果的精度取决于参数的精度,而不是赋值变量的精度。因此,**如果将一个通用数学函数的结果赋值给一个低精度的变量,可能会造成精度损失**。例如:
```fortran
real(kind=4) :: x, y
real(kind=8) :: z
x = 0.1
z = sin(x) ! z is double precision
y = z ! y is single precision, precision loss occurs
```
### 使用相同的精度的参数
通用数学函数的参数应该尽量保持相同的精度,以避免隐式类型转换和舍入误差。例如
```fortran
real(kind=4) :: x
real(kind=8) :: y, z
x = 0.1
y = 0.2d0 ! d0 suffix indicates double precision constant
z = cos(x + y) ! x is implicitly converted to double precision, rounding error may occur
```
> 通用数学函数可能会根据编译器和平台的不同而有不同的实现方式和性能。因此,在使用通用数学函数时,应该测试和验证其正确性和效率,并根据需要选择合适的编译选项或库
## Fortran内置数学函数
是指那些可以直接在Fortran程序中使用的标准函数,它们包括了常用的数学函数,如三角函数、指数函数、对数函数、特殊函数等。Fortran内置数学函数可以分为两类:
- 通用数学函数:这些函数可以接受不同种类(`kind`)的实型或复型参数,并根据参数的种类返回相应种类的结果的函数。例如,`sin(x)`函数可以接受单精度或双精度的实型参数,并返回相同精度的实型结果。通用数学函数是Fortran语言的内置函数,不需要声明或引用外部库。
- 特定数学函数:这些函数只能接受特定种类的实型或复型参数,并返回特定种类的结果的函数。例如,`r_sin(x)`函数只能接受单精度实型参数,并返回单精度实型结果。特定数学函数通常是Fortran编译器或库提供的扩展函数,需要声明或引用外部库。
以下是一些Fortran内置数学函数的列表,按照功能分类:
- 三角函数:`sin, cos, tan, asin, acos, atan, atan2, sinh, cosh, tanh, asinh, acosh, atanh`
- 指数和对数函数:`exp, log, log10, expm1, log1p`
- 幂和开方函数:`sqrt, cbrt, pow`
- 特殊函数:`erf, erfc, gamma, lgamma`
- 取整和取余函数:`floor, ceil, mod, modulo`
- 最大值和最小值函数:`max, min`
- 绝对值和符号函数:`abs, sign`
- 比特操作和查询函数:`bit_size, btest, ibits, ibclr, ibset, ishftc`
- 数值属性和控制函数:`digits, epsilon, huge, maxexponent, minexponent, precision, radix, range, tiny`
- 数值比较和分类函数:`isfinite, isinf, isnan
如何实现统一的精度控制,这取决于您的程序的需求和目标。一般来说,有以下几个建议:
- 尽量使用通用数学函数,以避免不必要的类型转换和精度损失。
- 尽量保持所有数值变量和常量的种类一致,以避免隐式类型转换和舍入误差。
- 尽量使用高精度的种类,如双精度或更高,以提高计算结果的准确性。
- 尽量使用编译器提供的选项或库来优化数值计算的性能和稳定性。
- 尽量测试和验证数值计算的正确性和效率,并根据需要调整代码或参数。