Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
gfortran在混合整数和实数计算中的精度损失_Fortran_Gfortran - Fatal编程技术网

gfortran在混合整数和实数计算中的精度损失

gfortran在混合整数和实数计算中的精度损失,fortran,gfortran,Fortran,Gfortran,我正在移植一些以前在IBMAIX4.3机器(IBMXLFortran)上运行的旧Fortran代码。在运行CentOS 7.7的x86_64机器上使用gfortran编译时,我在遗留代码中遇到了以下计算,该代码生成了错误的答案 ISCRATCH2 = ISCRATCH2 + (7 * (2.**16)) + TEMP2 ISCRATCH 2的初始值为X'0B000000',TEMP2的值为4053。计算结果为X'B070FD0',应为X'B070FD5'。如果我从2中删除点(使其成为整数而不是

我正在移植一些以前在IBMAIX4.3机器(IBMXLFortran)上运行的旧Fortran代码。在运行CentOS 7.7的x86_64机器上使用gfortran编译时,我在遗留代码中遇到了以下计算,该代码生成了错误的答案

ISCRATCH2 = ISCRATCH2 + (7 * (2.**16)) + TEMP2
ISCRATCH 2的初始值为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行得到一个浮点异常


这是预期的行为吗?如果是这样的话,如果我将其拆分为多行(ISCARTACH3计算),为什么它会得到正确的答案而不会引发浮点异常?我在CentOS 7.7上使用gfortran 4.8.5-39。这段代码似乎可以正确地与IBM编译器配合使用。我意识到以这种方式混合数据类型有点愚蠢,只需更改代码就可以解决这个问题。然而,在一个非常大的程序的代码中,很多地方都会用到这种东西。我能做些什么来解决这个问题,而不必找到这些实例中的每一个吗?

经过更多的实验后,问题似乎是(除了代码格式不好的事实之外)添加了0x0B000000,并且该数字超出了@steve建议的32位浮点精度。我认为原始语句中的情况是,因为其中一个值是实数,所以在赋值过程中将答案转换回整数之前,它会将它们全部转换为实数

进一步说明执行ISCRACH4=184549376+10时出现的问题。导致184549392,其中
ISCRACH4=184549376+10
导致184549386。有趣的是,
iscartch4=184549376+1。
只返回184549376。如果ISCRATCH4从和整数*4更改为实数*4,则所有表达式都返回正确答案


我发现如果我将
-fdefault-real-8
添加到编译选项中,答案总是正确的,浮点异常就会消失。我假设这是因为0x0B000000(或184549376)常量到实数的转换现在足够大,可以在不降低精度的情况下保持数字。此修复程序适用于我的应用程序。除了内存使用量的增加之外,还有什么原因不希望出现这种情况吗?

经过更多的实验,问题似乎是(除了代码格式不好的事实之外)添加了0x0B000000,并且该数字超出了@steve建议的32位浮点精度。我认为原始语句中的情况是,因为其中一个值是实数,所以在赋值过程中将答案转换回整数之前,它会将它们全部转换为实数

进一步说明执行ISCRACH4=184549376+10时出现的问题。导致184549392,其中
ISCRACH4=184549376+10
导致184549386。有趣的是,
iscartch4=184549376+1。
只返回184549376。如果ISCRATCH4从和整数*4更改为实数*4,则所有表达式都返回正确答案


我发现如果我将
-fdefault-real-8
添加到编译选项中,答案总是正确的,浮点异常就会消失。我假设这是因为0x0B000000(或184549376)常量到实数的转换现在足够大,可以在不降低精度的情况下保持数字。此修复程序适用于我的应用程序。除了内存使用量的增加之外,还有什么原因不希望出现这种情况吗?

代码显然是不符合Fortran标准的,因此编译器可以给出任何答案。十六进制文字常量以
Z
开头。十六进制不能出现在表达式中(即,第10行、第11行和第16行无效);实数在赋值时转换为整数,然后在后面的表达式中与其他整数相加;不,原因很简单。32位有符号整数的精度为31位。假设是32位IEEE-754浮点实体,
2.**16
的表达式具有24位精度。值得检查的是
2.0**16
本身有多少是[作为一个浮点数]。编译器/rtl可能使用可能给出不精确答案的公式
exp(16*ln(2.0))
。@Lorinczy,Fortran编译器可能将
2.*16
转换为
exp(16*ln(2.)
,但它不是一个很好的编译器。使用gfortran时,表达式是常数乘以4次乘法。代码显然是不符合Fortran的,因此编译器可以给出任何答案。十六进制文字常量以
Z
开头。十六进制不能出现在表达式中(即,第10行、第11行和第16行无效);实数在赋值时转换为整数,然后在后面的表达式中与其他整数相加;不,原因很简单。32位有符号整数的精度为31位。假设是32位IEEE-754浮点实体,
2.**16
的表达式具有24位精度。值得检查的是
2.0**16
本身有多少是[作为一个浮点数]。编译器/rtl可能使用可能给出不精确答案的公式
exp(16*ln(2.0))
。@Lorinczy,Fortran编译器可能将
2.*16
转换为
exp(16*ln(2.)
,但它不是一个很好的编译器。在gfortran中,表达式被4次乘法常数折叠。混合模式算法的规则在Fortran标准中有很好的规定<代码>2.*16是默认的实数类型。在表达式求值期间,RHS中的整数将提升为默认实数类型。