在现代 Fortran 中是否有必要将 _kind 附加到数字文字?
Is it necessary to append _kind to number literals in modern Fortran?
这可能是个愚蠢的问题,但在最近的一些测试后我有点困惑。我一直认为 Fortran 处理实数的方式如下(现代声明):
program testReal
implicit none
integer, parameter :: rkind=8
real(kind=rkind) :: a,b,c
// Test 1
a = 1
b = 1.
c = 1._rkind
write(*,"(2(1xES23.15))") a, b, c
// Test 2
a = 1/2
b = 1/2.
c = 1./2.
write(*,"(2(1xES23.15))") a, b, c
// Test 3
a = 3.3
b = 1 * a
c = 1. * a
write(*,"(2(1xES23.15))") a, b, c
end program testReal
除了Test 2 - a
之外,一切都一样。我一直以为我必须把例如1._rkind, 0.5_rkind, etc.
在每个实数之后以确保用零填充其余的尾数?
这只是纯粹的运气还是真的不再需要附加 _rkind
?
可以精确表示的数字不需要指定类型。所有不太大的整数都可以精确表示为 IEEE 标准浮点数。因此,没有必要像 1.
或 3.
这样的常量。还有一半可以用二进制表示,所以 1./2.
可以正常工作。
对于不能准确表示的其他值是必需的,因为没有后缀,文字被视为默认种类(单精度)。在你的情况下 3.3
不能完全表示,你会得到不同的结果
write(*,*) 3.3, 3.3_rkind
3.29999995 3.2999999999999998
我们先来看测试1。这里的1
、1.
和1._rkind
是常量。 1
是默认种类的整数; 1.
是默认种类的实数; 1._rkind
是种类 rkind
的实数(可能与默认种类相同)。这些都是不同的东西。
但是,在这种情况下,作业中发生的事情是关键。由于 a
、b
和 c
都是实数 rkind
相应的 right-hand 边都转换为实数 rkind
(假设这种类型比默认类型具有更高的精度)。转换等同于
a = REAL(1, rkind)
b = REAL(1., rkind)
c = 1._rkind
碰巧 1
和 1.
在您的数字模型中都可以完全转换为 1._rkind
.
我不会涉及测试 2,因为差异是 "obvious"。
在测试 3 中,我们有文字常量 3.3
,它是默认类型的实数。再次
a = REAL(3.3, rkind)
b = REAL(1, rkind)*REAL(3.3, rkind)
c = REAL(1., rkind)*REAL(3.3, rkind)
由于转化发生的地点和方式。从这里你可以看出结果是相当相同的,并且算术是真实的 rkind
.
您会注意到不同之处
a = 3.3
b = 3.3_rkind
因为(数学)实数 3.3 在您的数值模型中不能准确表示。并且近似值将与默认种类和种类 rkind
.
的实数不同
特别是"fill[ing] the rest of the mantissa with zeros".
不用担心
这可能是个愚蠢的问题,但在最近的一些测试后我有点困惑。我一直认为 Fortran 处理实数的方式如下(现代声明):
program testReal
implicit none
integer, parameter :: rkind=8
real(kind=rkind) :: a,b,c
// Test 1
a = 1
b = 1.
c = 1._rkind
write(*,"(2(1xES23.15))") a, b, c
// Test 2
a = 1/2
b = 1/2.
c = 1./2.
write(*,"(2(1xES23.15))") a, b, c
// Test 3
a = 3.3
b = 1 * a
c = 1. * a
write(*,"(2(1xES23.15))") a, b, c
end program testReal
除了Test 2 - a
之外,一切都一样。我一直以为我必须把例如1._rkind, 0.5_rkind, etc.
在每个实数之后以确保用零填充其余的尾数?
这只是纯粹的运气还是真的不再需要附加 _rkind
?
可以精确表示的数字不需要指定类型。所有不太大的整数都可以精确表示为 IEEE 标准浮点数。因此,没有必要像 1.
或 3.
这样的常量。还有一半可以用二进制表示,所以 1./2.
可以正常工作。
对于不能准确表示的其他值是必需的,因为没有后缀,文字被视为默认种类(单精度)。在你的情况下 3.3
不能完全表示,你会得到不同的结果
write(*,*) 3.3, 3.3_rkind
3.29999995 3.2999999999999998
我们先来看测试1。这里的1
、1.
和1._rkind
是常量。 1
是默认种类的整数; 1.
是默认种类的实数; 1._rkind
是种类 rkind
的实数(可能与默认种类相同)。这些都是不同的东西。
但是,在这种情况下,作业中发生的事情是关键。由于 a
、b
和 c
都是实数 rkind
相应的 right-hand 边都转换为实数 rkind
(假设这种类型比默认类型具有更高的精度)。转换等同于
a = REAL(1, rkind)
b = REAL(1., rkind)
c = 1._rkind
碰巧 1
和 1.
在您的数字模型中都可以完全转换为 1._rkind
.
我不会涉及测试 2,因为差异是 "obvious"。
在测试 3 中,我们有文字常量 3.3
,它是默认类型的实数。再次
a = REAL(3.3, rkind)
b = REAL(1, rkind)*REAL(3.3, rkind)
c = REAL(1., rkind)*REAL(3.3, rkind)
由于转化发生的地点和方式。从这里你可以看出结果是相当相同的,并且算术是真实的 rkind
.
您会注意到不同之处
a = 3.3
b = 3.3_rkind
因为(数学)实数 3.3 在您的数值模型中不能准确表示。并且近似值将与默认种类和种类 rkind
.
特别是"fill[ing] the rest of the mantissa with zeros".
不用担心