Fortran-要四舍五入到一个小数点吗
在fortran语言中,我必须将纬度和经度四舍五入到小数点后一位 我正在使用gfortran编译器和nint函数,但以下功能不起作用:Fortran-要四舍五入到一个小数点吗,fortran,rounding,gfortran,netcdf,Fortran,Rounding,Gfortran,Netcdf,在fortran语言中,我必须将纬度和经度四舍五入到小数点后一位 我正在使用gfortran编译器和nint函数,但以下功能不起作用: print *, nint( 1.40 * 10. ) / 10. ! prints 1.39999998 print *, nint( 1.49 * 10. ) / 10. ! prints 1.50000000 在这里寻找通用和特定的解决方案。例如: print '(5(1x, f0.1))', 1.30, 1.31, 1.35, 1.39,
print *, nint( 1.40 * 10. ) / 10. ! prints 1.39999998
print *, nint( 1.49 * 10. ) / 10. ! prints 1.50000000
在这里寻找通用和特定的解决方案。例如:
print '(5(1x, f0.1))', 1.30, 1.31, 1.35, 1.39, 345.46
没有办法按你的要求去做。潜在的问题是,您想要的舍入值不一定能够用浮点表示 例如,如果值为10.58,则在IEEE754 float32中精确表示为1.3225000 x 2^3=10.580000 当您将该值四舍五入到一个小数点时(无论您如何选择),结果将是10.6,但是10.6没有精确的表示形式。最接近的表示形式为1.3249999x2^3=10.599999(以浮点32表示)。因此,无论您如何处理舍入,都无法将10.6精确存储在float32值中,也无法将其作为浮点值写入netCDF文件。是的,可以做到!上面的“已接受”答案在其有限的范围内是正确的,但在Fortran(或其他各种HGL)中实际可以实现的方面是错误的 唯一的问题是,如果像写F(6.1)这样的东西失败了,你愿意付出什么代价 从一个角度来看,您的问题是“任意精度”计算主题的一个特别微小的变化。当您需要以精确的精度存储、操作和执行1024位数字的“数学”运算时,您认为加密是如何处理的 在这种情况下,一个简单的策略是将每个数字分成其组成部分“LHSofD”(十进制的左侧)和“RHSofD”值。例如,您可能有一个RLon(i,j)=105.591,并且希望将105.6(或任何舍入方式)打印到您的netCDF(或任何普通)文件中。将其拆分为RLonLHS(i,j)=105和RLonRHS(i,j)=591 。。。在这一点上,您可以选择增加通用性,但要付出一些代价。为了节省“钱”,RHS可能会保留为0.591(但如果需要做更高级的事情,则可放宽通用性) 为了简单起见,假设第二种策略是“便宜而快乐” LHS很简单(Int()) 现在,对于RHS,乘以10(如果您希望四舍五入到1 DEC),例如得出RLonRHS(i,j)=5.91,然后应用Fortran“四舍五入到最接近的整数”NInt()。。。留给你的是RLonRHS(i,j)=6.0 。。。鲍勃是你叔叔: 现在,您可以使用连接“Dual”的合适写入语句将LHS和RHS打印到netCDF中,并将根据OP中要求的目标创建精确的表示 。。。当然,以后读入这些值会返回到与上面所示相同的问题,除非读入也是ArbPrec感知的
。。。我们编写了自己的ArbPrec库,但在VBA和其他HGL中也有一些关于。。。但是请注意,一个完整的机器是一件非常重要的事情。。。幸运的是,问题很简单。正如其他人所说,问题在于NetCDF文件中使用浮点表示。使用
nco
实用程序,可以将纬度/经度更改为带有比例因子的短整数,并添加偏移量。像这样:
ncap2 -s 'latitude=pack(latitude, 0.1, 0); longitude=pack(longitude, 0.1, 0);' old.nc new.nc
“round_x=nint(x*10d0)/10d0”运算符将x取整(对于abs(x)<2**31/10,对于较大的数字,使用dnint()),并将取整后的值分配给round_x变量以供进一步计算
如上所述,并非所有小数点后有一个有效数字的数字都有精确的表示形式,例如,0.3没有
print *, 0.3d0
输出:
0.29999999999999999
1.3 1.3 1.4 1.4 345.5
要将舍入值输出到文件、屏幕或将其转换为小数点后有一个有效数字的字符串,请使用编辑描述符“Fw.1”(w-宽度w字符,0-可变宽度)。例如:
print '(5(1x, f0.1))', 1.30, 1.31, 1.35, 1.39, 345.46
输出:
0.29999999999999999
1.3 1.3 1.4 1.4 345.5
@JohnE,使用“G10.2”是不正确的,它将结果舍入到两个有效数字,而不是小数点后的一个数字。例如:
print '(g10.2)', 345.46
输出:
0.29999999999999999
1.3 1.3 1.4 1.4 345.5
0.35E+03
附言
对于NetCDF,取整应由NetCDF查看器处理,但是,您可以将变量输出为NC_字符串类型:
write(NetCDF_out_string, '(F0.1)') 1.49
或者,获得“漂亮”NC\U浮点/NC\U双倍数字:
beautiful_float_x = nint(x*10.)/10. + epsilon(1.)*nint(x*10.)/10./2.
beautiful_double_x = dnint(x*10d0)/10d0 + epsilon(1d0)*dnint(x*10d0)/10d0/2d0
p.p.S.@JohnE
unpacketed_data_value=packeted_data_value*scale_factor+add_of