双精度转四精度浮点数:哪个转换结果更准确?
咱们先把这两个四精度值的来龙去脉拆解开,你就能明白该选哪个了:
1. x_quad = real(x_double, kind=qp) 到底做了什么?
这个转换是完完整整把双精度变量x_double的二进制值转成四精度。因为四精度的精度比双精度高太多了,它能完全装下双精度的所有位信息,所以这个操作不会损失任何原始数据的精度——说白了,就是把你从二进制文件里读出来的那个双精度数,原封不动地“升级”成了四精度格式。
你打印出来的x_double值384.6433096437924其实是这个双精度数的十进制近似(浮点数打印时只会显示足够多的位数来唯一标识它,不会把所有十进制位都列出来)。而转换后的四精度值384.64330964379240681882947683334351,才是这个双精度数真实的十进制展开。
2. 384.64330964379240_qp 是怎么来的?
这个是直接把你手动写的十进制字符串384.64330964379240转成四精度浮点数。但这里有个关键细节:你打印出来的384.6433096437924只是原始双精度值的近似,不是它的精确十进制值。当你在后面加了个0变成384.64330964379240时,这个十进制数已经和原始双精度的真实值有一点点差异了——所以这个四精度值是这个手动输入的十进制数的最接近表示,和你从文件里读出来的原始数据并不完全一致。
该选哪个?
如果你的目标是准确保留原始双精度变量的所有信息,那x_quad = real(x_double, kind=qp)绝对是最优选择。它忠实地传递了原始数据的全部精度,没有引入任何额外误差。
而手动输入十进制数转换的方式,相当于用一个近似值重新造了一个四精度数,这个值和你真正要处理的原始数据有偏差,肯定不是正确的做法。
额外说一句
你的编译选项gfortran -fdefault-real-8只是把默认的real类型设为双精度,不会影响你代码里用selected_real_kind定义的dp和qp,所以这部分完全没问题。
内容的提问来源于stack exchange,提问作者user1887919

