回 帖 发 新 帖 刷新版面

主题:[讨论]任意多精度计算模块xp_module

今天在 www.fortran.com 这个网站找到一些很有用的模块

比如 xp_module 实现了任意多精度计算

如:

program test_xp
use xp_module
type(xp_real) :: x, y, z
call xp_set(100)
x = 1.0
y = 4.0
z = y * atan(x)
jform2 = 100
call xp_print(z)
end program test_xp

精确计算了pi的前100位

源程序见附件

回复列表 (共20个回复)

11 楼

[quote]
mltx 能说说在xp_module.f90中xp_real的值是什么吗?
谢谢![/quote]

xp_real是用户定义的数据类型:

1.0的数据类型是单精度实型;
1的数据类型是整型;
1.0_8的数据类型是双精度实型;
1.0_xp_real的数据类型是xp_real。

具体xp_real如何定义的,看源代码吧。

12 楼

受教。

13 楼

关心 fortran multi-precision 算法的人应该了解 David M. Smith 的FM package。
http://myweb.lmu.edu/dmsmith/FMLIB.html
应用 multi-precision 的好处是,一般的算法里不稳定的问题也可以计算。在我的应用里,每一次递推都要损失1位数字,而我需要递推110次左右。所以我需要130位有效数字。


应用的例子

....
use fmzm
....
  type(fm) :: a_fm,b_fm   !  defining fm variable
....
  call fm_set(130)        ! set 130 effective digits
.... 
   a_fm=1.d0     ! fm variable can be assigned by usual real*8 or integer

! a piece of my own code just showing it's easy to use
  do i=n_start,n_end
     kappa_fm(i)=ka_cenarc(i)
     theta_fm(i)=theta_cenarc(i)
     t0_fm(i)=t0_cenarc(i)

     m_fm(i)=1.d3
     li_fm(i)=li_cenarc(i)
     y0_fm(i)=y0_cenarc(i)
     z0_fm(i)=z0_cenarc(i)
     y_fm(i)=y0_cenarc(i)
     z_fm(i)=z0_cenarc(i)

     ny_fm(i)=ny0_cenarc(i)
     nz_fm(i)=nz0_cenarc(i)
     fi_fm(i)=irw(i)/10
     fo_fm(i)=orw(i)/10
     if(.not. flexible_roll) fi_fm(i)=0
     fi_fm(i)=0
  end do



14 楼

楼上的链接版本很老

我给一个最新的

http://crd.lbl.gov/~dhbailey/mpdist/

15 楼

好帖。外行的问下:不知道自定义数据精度xp_real 在cvf 和 powerstation4.0 编译器是不是都支持?
呵呵,有人会反对我又提powerstation4.0了。但我在程序调试时发现,有时cvf的bug,powerstation4.0能查出来。

16 楼


CVF6.6c,g95,gfortran是可以的,powerstation这东西太老,没用过

17 楼

请教自定义精度具体操作问题:
在subroutine 和 function 中,如果是双精度的运算,可以:

a = 2.0d0 * b * dcos(c)

这样解决。 在自定义精度下,子程序和自定义函数中的 常数和内部函数 怎么写成自定义的形式?
不会是:
a = 2.0xp0 * b * xpcos(c)
吧?

另,借贵帖谈对 fortran 精度的看法。 精度就是针对浮点数的。 为什么不能用一个语句定义整个
程序的运算精度呢?而非得对程序中出现的每个常数函数都加 d 才算数?
这样的语法科学吗?
我的意思是:是不是可以把程序中的参数分成浮点数、整数和字符串三类。如果程序开头定义了双精度,
那么程序中的函数和带小数点的常数就都属于程序开头定义的精度范围,而不必啰啰嗦唆的不停的 d。

18 楼

先定义类型:type(xp_real) :: x, y, z

然后确定精度:call xp_set(100)

再赋值:x = 1.0
        y = 4.0
        z = y * atan(x)

最后屏幕输出:call xp_print(z)

mltx说的那种方法:

x = 1.0_xp_real

y = 3.0_xp_real

好像不行

这个模块重载了赋值号"="

赋值号"="左边是type(xp_real)的话

其右边可以是integer,real(4),real(8),type(xp_real)

即把右边的类型转化为type(xp_real)


19 楼


今天上班之余,想了想实现任意多精度的方法,知道很繁杂,可是看完人家的代码后,还是很震撼!

20 楼

复杂的高精度请参考gmplib,速度很快,几千几万的阶乘也只需几毫秒

如果不要求精确值,请使用Stirling公式

简单的可以自己写写

我来回复

您尚未登录,请登录后再回复。点此登录或注册