数值类型转换根据一个值产生指定类型及kind的新值,原变量的类型和值不会因此改变。int、real和cmplx可通过可选的kind参数指定结果种类;dble则把参数转换为双精度实数。转换只作用于传入的表达式,写在运算之前还是之后,可能产生不同的计算结果。
适用场景
类型转换常用于把整数计数参与实数平均、把连续量划入整数档位、统一不同精度数据的计算种类,以及由实部和虚部构造复数。它也能明确表达程序希望在哪一步改变类型,避免赋值时的隐式转换掩盖整数除法或精度变化。
语法结构
integerValue = int(value [, kind])
realValue = real(value [, kind])
doubleValue = dble(value)
complexValue = cmplx(realPart [, imaginaryPart] [, kind])
- int把实数转换为整数时舍弃小数部分,方向是趋向零,而不是四舍五入或向下取整。
- real可以转换整数、实数或复数;复数转换为实数时只保留实部。
- dble返回双精度实数。现代代码需要明确精度时,通常使用real(value, kind=real64)表达得更清楚。
- cmplx由实部和可选虚部构造复数;处理高精度数据时应显式指定kind。
本文代码
! 显式类型转换用于控制计算方式和结果类型。
program conversionDemo
use iso_fortran_env, only: real64
implicit none
integer :: totalPulses, intervals
real :: convertedAfterDivision, realAverage
real(real64) :: doubleAverage
complex(real64) :: impedance
totalPulses = 25
intervals = 7
convertedAfterDivision = real(totalPulses / intervals)
realAverage = real(totalPulses) / real(intervals)
doubleAverage = dble(totalPulses) / dble(intervals)
impedance = cmplx(4.0_real64, 3.0_real64, kind=real64)
print "(A,F8.4)", "整数除法后再转换:", convertedAfterDivision
print "(A,F8.4)", "转换后执行实数除法:", realAverage
print "(A,F12.8)", "双精度平均值:", doubleAverage
print "(A,I0)", "int(-2.8) = ", int(-2.8)
print "(A,2F7.2)", "复阻抗的实部与虚部:", impedance
end program conversionDemo
编译运行
(base) hong@hongdeMacBook-Pro 043.conversion % gfortran -Wall -Wextra -std=f2018 exampleConversion.f90
(base) hong@hongdeMacBook-Pro 043.conversion % ./a.out
整数除法后再转换: 3.0000
转换后执行实数除法: 3.5714
双精度平均值: 3.57142857
int(-2.8) = -2
复阻抗的实部与虚部: 4.00 3.00
现象分析
在real(totalPulses / intervals)中,括号内的除法最先计算。25和7都是整数,而25可以写成7×3+4,所以整数除法只保留商3并舍弃余数4;随后real(3)得到默认实数3.0,赋给convertedAfterDivision后按F8.4显示为3.0000。转换发生得太晚,已经舍弃的余数无法恢复。
在real(totalPulses) / real(intervals)中,转换先得到默认实数25.0和7.0,除法因此按实数规则计算,结果约为3.5714285。F8.4只显示4位小数,并把下一位数字2舍去,所以终端显示3.5714。这里的格式只控制显示,不会把变量内部的值改成3.5714。
dble(totalPulses)和dble(intervals)分别得到双精度的25.0和7.0,双精度除法结果约为3.571428571428…。F12.8保留8位小数,第9位是1,因此显示3.57142857。更多数字来自双精度运算与更宽的输出格式共同作用;若源数据已经是发生过舍入的低精度实数,事后转换为双精度仍不能补回丢失的信息。
int(-2.8)舍弃小数部分得到-2,方向是趋近零,而floor(-2.8)才会得到-3。最后,cmplx(4.0_real64, 3.0_real64, kind=real64)构造4.0+3.0i;输出复数时,编辑描述符依次处理其实部4.00和虚部3.00。
核心知识点
- 转换函数产生新值,不会改变作为参数的原变量。
- 表达式先按操作数类型计算,再转换最终结果;需要实数除法时必须在整数除法发生前转换。
- int向零截断,不等同于nint、floor或ceiling。
- 改变kind不能恢复转换前已经丢失的数值信息;高精度计算应从高精度数据开始。
- 构造高精度复数时应为cmplx显式指定结果kind。