fortran - gfortran 在混合整数和实数计算中的精度损失
问题描述
我正在移植一些曾经在 IBM AIX 4.3 机器(IBM XL Fortran)上运行的旧 Fortran 代码。我在运行 CentOS 7.7 的 x86_64 机器上使用 gfortran 编译时在遗留代码中遇到了以下计算,该计算产生了错误的答案。
ISCRATCH2 = ISCRATCH2 + (7 * (2.**16)) + TEMP2
ISCRATCH2的初始值为X'0B000000',TEMP2的值为4053。计算结果为X'B070FD0',应该是X'B070FD5'。如果我从 2 中删除点(使其成为整数而不是实数),则该值是正确的。这是一个演示问题的小程序。
program main
implicit none
Integer*2 TEMP1
Integer*2 TEMP2
Integer*4 ISCRATCH1
Integer*4 ISCRATCH2
Integer*4 ISCRATCH3
ISCRATCH1 = X'0B000000'
ISCRATCH2 = X'0B000000'
TEMP1 = 4053
TEMP2 = 4053
ISCRATCH3 = 7 * (2.**16)
ISCRATCH3 = X'0B000000' + ISCRATCH3 + TEMP2
ISCRATCH1 = ISCRATCH1 + (7 * (2**16)) + TEMP1
ISCRATCH2 = ISCRATCH2 + (7 * (2.**16)) + TEMP2
Print 1102, ISCRATCH1, TEMP1
1102 FORMAT('ISCRATCH1 is ', Z8, ' and TEMP1 is ', Z8)
Print 1103, ISCRATCH2, TEMP2
1103 FORMAT('ISCRATCH2 is ', Z8, ' and TEMP2 is ', Z8)
Print 1104, ISCRATCH3, TEMP2
1104 FORMAT('ISCRATCH3 is ', Z8, ' and TEMP2 is ', Z8)
end program main
当我运行上述程序时,它会给出以下输出
ISCRATCH1 is B070FD5 and TEMP1 is FD5
ISCRATCH2 is B070FD0 and TEMP2 is FD5
ISCRATCH3 is B070FD5 and TEMP2 is FD5
如果我添加
-ffpe-trap=inexact
对于编译器选项,我在第 20 行得到一个浮点异常。
这是预期的行为吗?如果是这样,如果我将它分成多行(ISCRATCH3 计算),为什么它会得到正确的答案并且不会引发浮点异常?我在 CentOS 7.7 上使用 gfortran 4.8.5-39。这段代码似乎可以与 IBM 编译器一起正常工作。我意识到以这种方式混合数据类型有点愚蠢,只需更改代码即可解决。但是,这种东西在一个非常大的程序的代码中的很多地方都使用了。我可以做些什么来解决这个问题而不必找到每个实例?
解决方案
经过更多的实验后,问题似乎是(除了代码格式不正确的事实)添加了 0x0B000000 并且该数字超出了@steve 建议的 32 位浮点数的精度。我认为原始语句中发生的事情是,因为其中一个值是实数,所以在分配期间将答案转换回整数之前,它会将它们全部转换为实数。
为了进一步证明执行ISCRATCH4 = 184549376 + 10.
结果为 184549392 的问题,ISCRATCH4 = 184549376 + 10
结果为 184549386。有趣的是ISCRATCH4 = 184549376 + 1.
只返回 184549376。如果 ISCRATCH4 从 Integer*4 更改为 Real*4,则所有表达式都返回正确答案。
我发现如果我添加-fdefault-real-8
到编译选项中,答案总是正确的,浮点异常就会消失。我假设这是因为将 0x0B000000(或 184549376)常量转换为实数现在足够大,可以在不损失精度的情况下保持数字。此修复程序应该适用于我的应用程序。除了增加内存使用量之外,还有什么不受欢迎的原因吗?
推荐阅读
- c# - 从 C# 调用带有 void* 的 dll
- xamarin.forms - 从 UWP URI 协议方案启动未导航
- swift - 像在 SCNARView 中一样计算 worldFront
- android - 如何在android上的mysql中进行更改
- r - 在 R 中更快地读取和转换 .pdf 文件并将其转换为 .txt 文件?
- javascript - Jquery选择多个div
- javascript - Javascript 语法错误,单选按钮上无法识别的表达式
- spring-boot - 当 bootstrap.properties 存在时 application.properties 在 spring config 客户端中被忽略
- vba - 如果用户跳过行输入数值,则强制用户在以下可用行中输入数据
- angular - 在离子中创建一个模态,但以我自己的方式呈现它