主题:求助: 怎样 提高 实型变量精度
academician
[专家分:40] 发布于 2010-06-03 16:07:00
写一个代码
PROGRAM MAIN
REAL*8 A
A=1.123456789123456789
WRITE(*,*)A
END
输出为 1.12345683575
说明在使用双精度时 只能保证7位有效数字。
但是我在实际工作中 至少需要10位以上的精度。 这该怎样处理?
回复列表 (共8个回复)
沙发
asymptotic [专家分:16630] 发布于 2010-06-03 21:11:00
A = 1.123456789123456789D0
看来浮点数知识(缺乏)是一些同志永恒的“痛”。
板凳
adda [专家分:1520] 发布于 2010-06-03 21:55:00
A=1.123456789123456789_8
如果都需要10位以上高精度的话,最好在编译器中把浮点数的默认类型改为real8
3 楼
yuanhuzhouni [专家分:260] 发布于 2010-06-04 08:00:00
[quote]A = 1.123456789123456789D0
看来浮点数知识(缺乏)是一些同志永恒的“痛”。[/quote]
这个不说还真不知道,但是这个“浮点数知识”该怎么补习啊?
4 楼
academician [专家分:40] 发布于 2010-06-04 09:19:00
没明白啥意思~ 您给多解释解释呗
我要是很明白也不在这里问了
5 楼
weixing1531 [专家分:2580] 发布于 2010-06-04 09:40:00
加D就是双精度
没有D就是单精度
不像C语言默认为双精度
6 楼
yuanhuzhouni [专家分:260] 发布于 2010-06-04 10:00:00
[quote]
没明白啥意思~ 您给多解释解释呗
我要是很明白也不在这里问了[/quote]
你给A指定了real(kind=8),但是没给1.123456789123456789指定是什么类型,因此系统按默认规矩来,给他制定real(kind=4)。如果给常量后面加上D就表示他是双精度,即real(kind=8),这时最少有15位有效数字。
多亏楼上几位大侠,我也多学到一些。
7 楼
academician [专家分:40] 发布于 2010-06-04 10:30:00
我总结了下:
网上关于 浮点数数的解释:
浮点数型态 (REAL)
--------------------------------------------------------------------------------
real a
未指定kind值时,通常宣告为单精准度(kind=4)
单精准度 - 使用4字节(4 bytes, 32 bits)
real(kind=4) a ! F90新增作法
real(4) b !
REAL*4 c ! F77传统作法
可表示范围(PC):±1.18*10-38 ~ ±3.40*1038
单精准度有效位数为6-7位,注意可能有以下问题:
a = 1000000. + 0.1 → a = 1000000. ← 常见错误,大数加小数!
双精准度 - 使用4字节(8 bytes, 64 bits)
real(kind=8) a ! F90新增作法
real(8) b !
REAL*8 c ! F77传统作法
可表示范围(PC):±2.23*10-308 ~ ±1.79*10308
双精准度有效位数为15位
使用注意:
可用科学记号表示法,如
10,000,000,000 = 1E10
0.0000000001 = 1E-10
双精准度时请将E改为D,如1D10、1D-10
常数部分请加上".0",如3 → 3.0(只加"."亦可)
real a
a= 1.5 + 3./2. → a= 3.0 (3.与2.被视为浮点数,以浮点数来记录结果)
a= 1.5 + 3/2 → a= 2.5 (3/2视为整数,小数无条件舍去)← 常见错误!
由于只要写成 3./2 就可以得到正确答案(分子或分母有一为实数),所以这里常有人以为「计算式中有一个变量或常数是实数就可以了」,其实不尽然对,比如在摄氏转华氏的问题中:
1. Ft = Ct * 9/5 + 32 可得正确数字
2. Ft = 9/5 * Ct + 32 会变成 Ft = 1*Ct + 32
3. Ft = Ct*(9/5) + 32 也变成 Ft = Ct*1 + 32
理由在于「算述运算子的优先次序」,第 2 式 9/5 先被计算,因为 9 和 5 都是整数,所得结果会被放入一个整数型态的计算缓存器,此时 9/5 便成为整数 1 ,而非正确的 1.8,再和 Ct 做乘法。
第 3 式中,由于刮号内 9/5 优先被计算,所以也变成了 1 。
许多FORTRAN编译器中,计算缓存器会以算式中需要位数最多的数值做为标准,所以
1/3 → 1和3都是整数,以integer为计算缓存器配置(所以你才会得到1/3=0)
1./3 → 1. 为 real*4 ,以 real*4 为计算缓存器配置
1.d0/3 → 1.d0 为 real*8 ,以 real*8 为计算缓存器配置
当然最好养成习惯,每个常数都改成正确的实数表示方法,而不要只偷懒改其中一个
但CVF 6.5 并非如此,在测试中我们发现实数部分一律使用了 real*8
有些FORTRAN编译器,不会看到上述的错误,比如其计算缓存器一律采用 REAL * 8 型态,则不会有上述因系统自行判断,使用了整数缓存器所产生的不预期结果。
双精准度(REAL*8),常数请加上"d0",如3 → 3d0 或 3.d0 ← 常见忽略!
a = 1/3 → a = 0.0000000000000000
a = 1./3. → a = 0.3333333432674408
a = 1D0/3D0 → a = 0.3333333333333333
"D"不分大小写,其意义同为科学记号表示法
或采用 a = 1.0_4 表示 kind = 4 ! F90新增作法
a = 1.0_8 表示 kind = 8 ! F90新增作法
对于该贴这个问题:
#写一个代码
#
# PROGRAM MAIN
# REAL*8 A
# A=1.123456789123456789
# WRITE(*,*)A
# END
#输出为 1.12345683575
编译器的计算缓存器的配置默认应该是real*4
虽然A为双精度型 但是编译器会把1.123456789123456789当做单精度处理。
因此,A的赋值会发生变化。
因此 正常我们做加减乘除的时候 表达式中的实型常数会被当做单精度处理
比方:
#
# PROGRAM MAIN
# REAL*8 A
# A=1.123456789123456789*1.0
# WRITE(*,*)A
# END
A的值相当于两个单精度数的计算结果。
要得到双精度的结果
表达式要变为
A=1.123456789123456789D0*1.0D0
8 楼
幸运的人儿 [专家分:0] 发布于 2010-06-10 06:33:00
编写一个函数,用指针作为参数,分别得到双精度实型数据的整数部分和小数部分的相关内容
我来回复