Fortran 90解析NetCDF时间戳时小数部分丢失问题排查
问题分析
你的问题核心在于单精度浮点数的精度不足,导致时间戳的小数部分直接丢失。
单精度real类型的有效数字只有6-7位左右,而你的时间戳整数部分(比如20220101)已经是8位数字,这时候单精度浮点数根本存不下后面的小数部分(0.02083这类值),直接把小数截断成0了——这就是为什么timeStamp - floor(timeStamp)始终返回0,打印出来的全是整数日期。
修复方案
把所有和时间戳相关的real类型换成双精度浮点数(double precision或real(kind=8)),具体修改后的代码如下:
function parseTimeStamp (timeStamp) implicit none double precision, dimension(5) :: parseTimeStamp double precision, intent(in) :: timeStamp double precision :: date integer :: intdate, day, month, year date = floor(timeStamp) ! 提取日期整数部分 parseTimeStamp(4) = timeStamp - date ! 保存日分数 intdate = int(date) day = mod(intdate,100); intdate = intdate / 100 month = mod(intdate,100); intdate = intdate / 100 year = intdate parseTimeStamp(1) = dble(year) parseTimeStamp(2) = dble(month) parseTimeStamp(3) = dble(day) end function parseTimeStamp
另外注意:读取NetCDF文件的时候,也要保证读取变量的类型是双精度,别在读取阶段就把精度丢了。
验证小技巧
- 打印
timeStamp时用双精度格式符,比如write(*, '(F12.5)') timeStamp,确保小数部分能正常显示出来。 - 可以自己写个小测试:定义
double precision :: test = 20220101.02083d0,打印看看是不是能完整保留小数。
内容的提问来源于stack exchange,提问作者Daniel Mutton
相关产品推荐
相关产品推荐

