找回密码
 欢迎注册
楼主: 云梦

[原创] 真正的高精度科学计算器

[复制链接]
 楼主| 发表于 2013-1-16 18:56:27 | 显示全部楼层
感觉是特殊问题特殊处理,不可能处理一般情况
mathe 发表于 2013-1-16 17:35

一般情况当然很好处理,也就不需要什么特殊的方法。针对不同的问题采取不同的方法才是灵活可取的。如果不灵活的话,那么解这个方程要求的精度太高了。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2013-1-16 19:00:32 | 显示全部楼层
我的计算器精度虽然不高,但在绝大多数情况下均能保持这个精度,复杂和简单的运算正是数学函数以及表达式的组成元素。
例如:如果不用数学软件,计算不完全伽马函数及正则不完全伽马函数,在0-10^14内的实数你可否能保持高的精度及正确结果?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2013-1-16 23:46:50 | 显示全部楼层
针对不同的问题采取不同的方法才是灵活可取的。
云梦 发表于 2013-1-16 18:56

大型软件如Mathematica,MATLAB都不敢说一条命令通吃所有问题,
你这个小小的计算器也不大可能点一下按钮,或者输入方程,敲一个命令,就给出图片中方程解的超高的精度。
所以我宁愿相信,你特地为这个方程写了一段代码,放在计算器里面,
然后说我的计算器可以完美的解决这种问题,而其他的数学软件不能。这有什么意义呢。
========
先不谈意义,就题论题,该问题总得有具体的算法实现吧,
不采用mathe的处理方式,我实在是想不出其他的方法,
能否共享一下此题的算法实现

毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2013-1-17 07:59:30 | 显示全部楼层
不需要什么特殊代码,只是利用了该方程的特点,x=a+s*10^-r。这样就可以把整数和小数分离,只计算小数部分。83楼也就是利用了近似的特点得到了近似值。不过他的x值只是我程序中x的初始值罢了。
下面就需要用牛顿法进行迭代,在迭代时只计算小数部分,这样不就得到较精确的结果了吗?其实这只是一个小技巧。技巧编程可以解决很多不容易解决的问题。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2013-1-17 08:14:01 | 显示全部楼层
把方程整理一下,变成以下格式,即可以求出方程的初始值。
把左式与右式的差进行求导,得到下面最后一个公式。
1.JPG
2.JPG
3.JPG
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2013-1-17 08:17:46 | 显示全部楼层
如果你能看懂我的VB程序,你就分析一下,吧。
NameF.Text = "F(x) ="
Dim Ii, xChen0, Xp0 As Single
    Dim cv As String * 2000
    xChen0 = ychen
    Xp0 = xP
    Call SJbz
Select Case ychen
   Case 64
      xP = 24
      xChen = 80
   Case 128
      xP = 45
      xChen = 160
   Case 256
      xP = 85
      xChen = 300
End Select
Xspd = 0
Call SJbz
Wx = Ax
An = SToo(0)
Bn = SToo(1)
Ax = An
Bx = Bn
hsfx = "-"
Call Addition
If Left(Ax.St, 1) <> 0 And An.bz = "" And Bn.bz = "" Then 'A -B <> 0
    '初始值 x0
   If Left(Xy.St, 1) = "1" Or Left(Xy.St, 1) = "3" Then 'C=0
         If Ax.bz = "" Then  '如果A>B A-B交换
             An = SToo(1)
             Bn = SToo(0)
         End If
         Call Dj01     '计算初始值 x0
         Ax = SToo(3)
        If Xspd = 0 Then
           For Ii = 0 To 100
                Call Dj2012   'x 带入原方程
                'SToo(4) = Ax
                Call Dj2012F  '导数
                SToo(5) = Ax
                Cx = SToo(4)
                Ax = SToo(5)
                Call multx_    'F(x)/F'(x)
                Bx = Cx
                Ax = SToo(3)
                hsfx = "-"
                Call Addition
                If Left(Bx.St, 1) = "0" Or Bx.zs < -xChen - 20 Then
                   SToo(3) = Ax
                   Call Dj2012
                   SToo(4) = Ax
                   Exit For
                End If
                SToo(3) = Ax
               
          Next
        Else
           '仅计算小数部分    '(2by)^(1/2)*d^b
           Ax = Bn
           Bx = Bn
           hsfx = "+"
           Call Addition  '2b
           
           Cx = SToo(3)
           Call mult_     '2by
           Ax = Cx
           Call Lnx
           Cx.bz = ""
           Cx.St = "5"
           Cx.zs = -1
           Call mult_
           Ax = Cx
           Call Exp       '(2by)^(1/2)
           Px = Ax
           
           Ax = Dn        'd
           Call Lnx
           Cx = Bn        'b
           Call mult_
           Ax = Cx
           Call Exp      'd^b
           
           Cx = Px
           Call mult_
           Ax = Cx
           SToo(4) = Ax
           
           '2b/a*(b^2-a^2)^(1/2)d^b*y
           Ax = Ajn(1)
           Cx = Bn
           Call mult_
           Ax = An
           Call multx_
           Ax = Cx
           Bx = Cx
           hsfx = "+"
           Call Addition
           Px = Ax
           
           Ax = Dn
           Call Lnx
           Cx = Bn
           Call mult_
           Ax = Cx
           Call Exp
           Cx = Px
           Call mult_   '*d^b
           Ax = SToo(3)
           Call mult_
           Ax = SToo(3)
           
           Bx = Cx
           hsfx = "+"
           Call Addition
        End If
   Else
     '数值验证 ,=0
     Call SJbz
     Call Dj2012
   End If
   
   
Else     '如果 A=B 根x=A
   Ax = An
   SToo(3) = An
End If
'结果显示处理

Form1.Height = 5900
If Left(Xy.St, 1) = "1" Then   '显示根
   If Xspd = 0 Then
       Ax = SToo(3)
       xChen = xChen - fn0
       Call sc(Ax.bz, Ax.St, Ax.zs)
    Else
   '只计算小数部分时
      For Ii = xChen + 20 To Bn.zs + 1 Step -1
          If Mid(Bn.St, Ii, 1) <> "0" Then
               Bn.St = Left(Bn.St, Ii)
          End If
      Next
      Call sc(Ax.bz, Ax.St, Ax.zs)
      Ax = SToo(3)
      cv = Left(Bn.St, Bn.zs + 1) + "." + IIf(Ii - Bn.zs = 0, "", Mid(Bn.St, Bn.zs + 1, Ii - Bn.zs)) + "  +  " + Left(Ax.St, 1) + "." + Mid(Ax.St, 2, ychen - 1) + " E" + CStr(Ax.zs)
   '在下窗口按精度显示
      Text11.Text = cv
      
   End If
Else   '显示验证结果
   Ax = SToo(4)
   
   Call sc(Ax.bz, Ax.St, Ax.zs)
End If
       xChen = xChen0
       xP = Xp0
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2013-1-17 08:20:21 | 显示全部楼层
Function Dj2012()  '原方程

Yn1 = Ax
Cx = Ax
Call mult_
Xx = Cx   'x^2

Ax = An
Cx = An
Call mult_
Yx = Cx    'A^2

Ax = Bn
Cx = Bn
Call mult_
Rx = Cx     'B^2

Ax = Xx
Bx = Yx
hsfx = "-"        'x^2-a^2
Call Addition
Call Lnx
Ajn(10) = Ax   'ln(x^2-a^2)

Cx.bz = ""
Cx.St = "5"
Cx.zs = -1
Call mult_
Ax = Cx
Ajn(7) = Ax     'Ln(x^2 - a^2)^(1/2))
Call Exp
Ajn(2) = Ax     '(x^2 - a^2)^(1/2)
Ax = Yn1
Bx = Ajn(2)
hsfx = "-"
Call Addition
Ajn(4) = Ax     'x-(x^2 - a^2)^(1/2)


Ax = Xx
Bx = Rx          'x^2-b^2
hsfx = "-"
Call Addition
Call Lnx
Cx.bz = ""
Cx.St = "5"
Cx.zs = -1
Call mult_
Ax = Cx
Ajn(8) = Ax    'Ln(x^2 - b^2)^(1/2))

Call Exp
Ajn(3) = Ax       '(x^2 - b^2)^(1/2)
Ax = Yn1
Bx = Ajn(3)
hsfx = "-"
Call Addition
Ajn(5) = Ax     'x-(x^2 - b^2)^(1/2)
Call Lnx

Ax = Ajn(4)
Call Lnx
Qbx = Ax        'Ln(x-(x^2-a^2)^(1/2))

Ax = Ajn(5)
Call Lnx
Qby = Ax        'Ln(x-(x^2-b^2)^(1/2))

Ax = Bn
Cx = An
Call multx_    'a/b
Ajn(6) = Cx
Ax = Cx
Call Lnx       'ln(a/b)
Ajn(9) = Ax

Bx = Ajn(8)
hsfx = "+"
Call Addition
Bx = Ajn(7)
hsfx = "-"
Call Addition
Call Exp
Wn = Ax   '[a(x^2-b^2)^(1/2)/(b(x^2-a^2)^(1/2)]   ok


Ax = Qbx
Bx = Qby
hsfx = "-"
Call Addition   'Ln[a(x-(x^2-b^2)^(1/2))/(b(x-(x^2-a^2)^(1/2))]
Bx = Ajn(9)
hsfx = "-"
Call Addition   'b/a
Cx = Yn1
Call mult_
Ax = Cx
Call Exp
Bx = Ax
Ax = Wn
hsfx = "-"
Call Addition
SToo(4) = Ax
End Function
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2013-1-17 08:20:57 | 显示全部楼层
Function Dj2012F()
'求导数
'1)
Ax = Ajn(7)
Bx = Ajn(8)
hsfx = "+"
Call Addition
Bx = Ax
Ax = Ajn(9)
hsfx = "-"
Call Addition
Call Exp
Cx = Yn1
Call mult_
Ajn(14) = Cx       'ax/(b(x^2-a^2)^(1/2)(x^2-b^2)^(1/2))   ok

'2)
Ax = Ajn(8)
Bx = Ajn(7)
hsfx = "-"
Call Addition
Bx = Ajn(10)
hsfx = "-"
Call Addition
Bx = Ajn(9)
hsfx = "+"
Call Addition
Call Exp
Cx = Yn1
Call mult_
Ajn(15) = Cx       'ax(x^2-b^2)/(b(x^2-a^2)^(3/2))    ok

'3)
Ax = Ajn(3)
Cx = Yn1
Call multx_

Bx = Cx
Ax.bz = ""
Ax.St = "1"
Ax.zs = 0
hsfx = "-"
Call Addition  '1-x/(x^2-b^2)^(1/2)
Tx = Ax

'4)
Ax = Qby
Bx = Ax
hsfx = "+"
Call Addition
Bx = Ax
Ax = Qbx
hsfx = "-"
Call Addition
Bx = Ajn(9)
hsfx = "-"
Call Addition
Call Exp
Cx = Tx
Call mult_   'b(x-(x^2-a^2)^(1/2))(1-x/(x^2-b^2)^(1/2))/a/(x-(x^2-b^2)^(1/2))   ok
Tx = Cx

'5)
Ax = Ajn(2)
Cx = Yn1
Call multx_
Bx = Cx
Ax.bz = ""
Ax.St = "1"
Ax.zs = 0
hsfx = "-"
Call Addition  '1-x/(x^2-a^2)^(1/2)
Cx = Ax
Ax = Ajn(5)
Call multx_
Ax = Ajn(6)
Call multx_
Ax = Cx
Bx = Tx
hsfx = "-"
Call Addition
Cx = Ajn(5)
Call mult_
Ax = Ajn(4)
Call multx_
Ax = Ajn(6)
Call mult_
Ax = Yn1
Call mult_
Tx = Cx

'6)
Ax = Qbx
Bx = Qby
hsfx = "-"
Call Addition
Ax = Ax
Bx = Ajn(9)
hsfx = "-"
Call Addition
Bx = Tx
hsfx = "+"
Call Addition
Tx = Ax

'7)
Ax = Qbx
Bx = Qby
hsfx = "-"
Call Addition
Bx = Ajn(9)
hsfx = "-"
Call Addition
Cx = Yn1
Call mult_
Ax = Cx
Call Exp
Cx = Tx
Call mult_
Bx = Cx
Ax = Ajn(14)
hsfx = "-"
Call Addition
Bx = Ajn(15)
hsfx = "-"
Call Addition
End Function
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2013-1-17 08:26:30 | 显示全部楼层
不需要什么特殊代码,只是利用了该方程的特点,x=a+s*10^-r。这样就可以把整数和小数分离,只计算小数部分。83楼也就是利用了近似的特点得到了近似值。不过他的x值只是我程序中x的初始值罢了。
下面就需要用牛顿法进 ...
云梦 发表于 2013-1-17 07:59


这也可看做是一种特殊的优化。

打个比方,要算1000万个连续“7”构成的大整数的平方,如果能敏感的抓住其特征,转化为
$(7//9xx(10^1000-1))^2=(10^2000-2xx10^1000+1)xx49//81$

这样,将比普通的通用算法效率高很多。
我在 HugeCalc 里就大量应用了类似优化,
北大的刘楚雄老师曾以该特殊值(因为好输入)测试 HugeCalc,
结果速度之快令其大吃一惊!
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2013-1-17 09:01:25 | 显示全部楼层
当然,计算器毕竟就是计算器,离不开按钮,但是每个按钮下的文章就无法想象了。如果这个方程经常被使用,当然可以放在按钮下,解决了很多不易记忆的命令行和不必要的重复劳动,这正是本计算器的目的之所在。
唯一最大的弱点就是计算速度不令人满意,HugeCalc 我也想利用,可小数转换成整数很麻烦,且计算中不需要那么多的整数,能保证一定精度就可以了。大整数运算需要消耗大量的存储资源,用VB调用HugeCalc中的函数虽然基本运算速度大大提高,可毕竟涉及的是大量的小数,因此转换消费的时间降低了效率。
作为计算器具有128位精度其实已经大大超出了常规计算器,且丰富的函数也是现计算器中没有的,更高的精度会降低运算速度,所以常用的是64位和128位,256位以上似乎没有什么意义,但仍保留到1024位,为特殊人群服务。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-4-24 12:30 , Processed in 0.057212 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表