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
Arrays 在Fortran数组构造函数中引起问题的浮点_Arrays_Fortran_Fortran90 - Fatal编程技术网

Arrays 在Fortran数组构造函数中引起问题的浮点

Arrays 在Fortran数组构造函数中引起问题的浮点,arrays,fortran,fortran90,Arrays,Fortran,Fortran90,我有点被一些与Fortran数组构造函数相关的错误所困扰。也许你能帮我理解错误?我特别有两个问题(见下文) 我最简单的工作示例是: program debug use ieee_arithmetic implicit none integer :: ii real, parameter :: KZERO = 1 real, parameter :: LAMBDA = 1.3 integer, parameter :: pad = 5

我有点被一些与Fortran数组构造函数相关的错误所困扰。也许你能帮我理解错误?我特别有两个问题(见下文)

我最简单的工作示例是:

program debug

use ieee_arithmetic
implicit none

integer :: ii

real, parameter      :: KZERO   = 1
real, parameter      :: LAMBDA  = 1.3

integer, parameter      :: pad     = 5            
integer, parameter      :: nsh     = 60 + 2*pad    
integer, parameter      :: top=nsh-pad, bot=pad+1  

real(kind=8),    parameter :: dt2 = 1.0D-5/2
real(kind=8),    parameter :: VK_SS = 6.0D-10 
real(kind=8),    parameter :: VM_SS = 6.0D-05

real(kind=8), parameter,dimension(nsh) :: k  = [(KZERO*LAMBDA**(ii-pad), ii=1, nsh)] 
real(kind=8), parameter,dimension(nsh) :: NUK_K = [(-dt2*VK_SS*k(ii)**2, ii=1, nsh)]  
real(kind=8), parameter,dimension(nsh) :: NUK_M = [(-dt2*VM_SS*k(ii)**2, ii=1, nsh)]  

real(kind=8),    parameter, dimension(nsh) :: A = [(.0,ii=1,pad), ( REAL(exp(NUK_K(ii))), ii=bot, top), (.0,ii=1,pad)] 
real(kind=8),    parameter, dimension(nsh) :: B = [(.0,ii=1,pad), ( REAL(    NUK_M(ii) ), ii=bot, top), (.0,ii=1,pad)]
!real(kind=8),    parameter, dimension(nsh) :: C = [(.0,ii=1,pad), ( REAL(exp(NUK_M(ii))), ii=bot, top), (.0,ii=1,pad)]

print *,A 
print *,'-------------------------'
print *,B
print *,'-------------------------'
!print *,C

end program debug

第一个问题:我为什么需要在定义了A、B和C的构造函数中使用REAL()进行类型转换?如果没有,则会出现以下错误:

/opt/intel/composer_xe_2011_sp1.9.293/bin/intel64/ifort  -o debug debug.f90 
debug.f90(23): error #7113: Each ac-value expression in an array-constructor must have the same type and type parameters.   [EXP]
real(kind=8),    parameter, dimension(nsh) :: A = [(.0,ii=1,pad), ( exp(NUK_K(ii)), ii=bot, top), (.0,ii=1,pad)] 
--------------------------------------------------------------------^
…但是do循环元素已经是真正的=8了,因为NUK_K是

第二个问题:当我取消对定义C的行的注释时(也是通过数组构造函数),我得到以下错误:

/opt/intel/composer_xe_2011_sp1.9.293/bin/intel64/ifort  -o debug debug.f90 
debug.f90(25): warning #7919: The value was too small when converting to REAL(KIND=4); the result is zero.
real(kind=8),    parameter, dimension(nsh) :: C = [(.0,ii=1,pad), ( REAL(exp(NUK_M(ii))), ii=bot, top), (.0,ii=1,pad)]
--------------------------------------------------------------------^
debug.f90(25): error #7768: This operation on this data type is currently inaccurate.
real(kind=8),    parameter, dimension(nsh) :: C = [(.0,ii=1,pad), ( REAL(exp(NUK_M(ii))), ii=bot, top), (.0,ii=1,pad)]
--------------------------------------------------------------------^
…警告是正常的,因为我猜这意味着编译器建议exp(-[large number])->0,对吗? 但我如何处理错误“此数据类型上的操作当前不准确”

我希望你能帮助我,因为我已经在这个问题上花了很长时间了

编辑 首先,非常感谢您提供的有用答案!我非常感激。然而,不准确的问题仍然存在。有什么想法吗?我最初的猜测是使用四元组而不是双元组,然后将结果转换为双元组(我的CPU本机不支持四元组)。这也行不通。我新的最小工作示例是(注意,我删除了零填充以使示例更简单):

但这仍然会产生错误

/opt/intel/composer_xe_2011_sp1.9.293/bin/intel64/ifort  -o debug debug.f90 
debug.f90(30): error #7768: This operation on this data type is currently inaccurate.
real(df),    parameter, dimension(nsh) :: C = [ ( exp(NUK_M(ii)) , ii=1, nsh) ]
--------------------------------------------------^

第一个问题:

您试图将一个数组
(.0,ii=1,pad)
,它是默认类型
real(4)
,与数组
(real(exp(NUK(ii)),ii=bot,top)
,它是
real(8)
。最简单的解决方案是将第一个数组也变成
实数(8)
数组,例如用
0.0d0
替换浮点数
.0
(双精度数字的科学表示法)

例如:

real(kind=8), parameter, dimension(nsh) :: A = [(0.0d0,ii=1,pad), ( exp(NUK_K(ii)), ii=bot, top), (0.0d0,ii=1,pad)]
real(kind=8), parameter, dimension(nsh) :: B = [(0.0d0,ii=1,pad), (     NUK_M(ii) , ii=bot, top), (0.0d0,ii=1,pad)]
real(kind=8), parameter, dimension(nsh) :: C = [(0.0d0,ii=1,pad), ( exp(NUK_M(ii)), ii=bot, top), (0.0d0,ii=1,pad)]
第二个问题:

默认情况下,
real(num)
不会将数字
num
键入
real(8)
,而是键入默认种类
real(4)
。如果要将其类型转换为
real(8)
,则必须使用符号
real(num,kind=8)
显式执行此操作


换句话说,你一直在做的是,从双精度到单精度浮点显式地类型转换
(exp(NUK_M(ii)),ii=bot,top)
,然后用一个单精度的零数组连接它,然后再将结果类型转换到一个双精度数组。这就是编译器抱怨精度损失的原因。

对于可能感兴趣的人,请跟进:

我决定做一个骇人的解决方案来解决关于内在函数exp()精度的问题。 问题是我希望计算exp(-[very large number]),它变得太接近零,甚至四元浮点也无法表示大(负)指数。问题是,我不能简单地将这些条目设置为零,因为这会干扰整个问题的数值。
因此,我所做的是用exp(-7.0D2)替换exp(-7.0D2),这接近使用double表示的极限

这两个问题是相关的,但不是以一种很容易让你找到其他资源的方式。本质上,思考“当我忽略左边的东西时,右边的东西是如何评估的?”。数组构造函数不知道
nuk_k
的类型;求幂运算不知道
c
的类型。因此,查找构造的数组的类型,使用显式种类常量的
real()
的结果是丑陋和不可移植的。此外,如果你有一个种类常数,比如说
rp
,那么
real(rp)
real(kind=8)
还要短,你可以省略
kind=
。谢谢你的回答,并建议了定义不同种类实数的正确方法。我同意,这样比较好。然而,不准确的问题仍然存在,你可以在我编辑的答案中看到。有什么想法吗?你不能保证0.0d0是一个实物值为8的实数,我可以向你展示一些不真实的情况。此外,您不能保证reals的类型值为8对于您正在使用的编译器是有效的,我可以再次给出一个示例。在这个时代,您不应该使用d0,也不应该对种类值使用显式常量。更确切地说,请参阅一点简介默认种类是默认种类,只有在某些编译器中它是4。它是在现实世界中可以遇到的其他几种编译器中的第一种。此外,大多数编译器可以设置为使用8字节实数作为默认类型,然后
双精度
(或
1d0
)将为16字节,尽管在gfortran中
kind=8
仍将是
8字节
。换句话说,gfortran可以设置为使用
kind=8
作为双精度,有些人确实使用此设置(即使在这里的问题中)。我在回答中没有使用kind变量的原因是,根据他/她提供的示例代码,我试图尽可能具体地解决OPs问题。但我同意,一般来说,使用种类变量是更好的做法。(在我自己的代码中,我总是定义
dp=real64
,其中
real64
是从
iso\u fortran\u env
导入的,并且会为常量编写
0.0\u dp
而不是
0.0d0
。)非常感谢您的回答。它们非常有用,我采用了速记方法来定义浮点类型。然而,不准确的问题仍然存在,正如您可以从我上面编辑的问题中看到的。有什么想法吗?为什么不定义自己的exp_new(x),为x<7.0D2调用内在exp(x),并为x>7.0D2使用简单的泰勒展开?
real(kind=8), parameter, dimension(nsh) :: A = [(0.0d0,ii=1,pad), ( exp(NUK_K(ii)), ii=bot, top), (0.0d0,ii=1,pad)]
real(kind=8), parameter, dimension(nsh) :: B = [(0.0d0,ii=1,pad), (     NUK_M(ii) , ii=bot, top), (0.0d0,ii=1,pad)]
real(kind=8), parameter, dimension(nsh) :: C = [(0.0d0,ii=1,pad), ( exp(NUK_M(ii)), ii=bot, top), (0.0d0,ii=1,pad)]