使用Java实现的高精度科学计算器
高精度科學(xué)計(jì)算器
混合運(yùn)算展示:
精度展示:
簡介:
可以進(jìn)行混合運(yùn)算,混合運(yùn)算包括加法+,減法-,乘法*,除法/,取余%,左括號(,右括號),根號√,對數(shù)log,指數(shù)^。
如:輸入:(3+2)^2+108/5-10log2+3√64
? 輸出:47.27807190511263678372
理論可以達(dá)到無限精度,過高的精度會增加計(jì)算時(shí)間,需要提前設(shè)置精度,即小數(shù)點(diǎn)后多少位,默認(rèn)為32位。
按鍵功能及使用方法:
| CE | 清空 | 點(diǎn)擊該鍵清空輸入輸出 | 
| ← | 清除 | 點(diǎn)擊該鍵清除最后一位輸入 | 
| Exp | 指數(shù)表示 | 正在更新。。。 | 
| +/- | 符號切換 | 正在更新。。。 | 
| + | 加法 | 可用于混合運(yùn)算,輸入“被加數(shù)”,“+”,“加數(shù)”后點(diǎn)擊“=”計(jì)算結(jié)果 | 
| - | 減法 | 同加法 | 
| * | 乘法 | 同加法 | 
| / | 除法 | 同加法 | 
| Mod | 取余 | 同加法,按鍵顯示為“Mod”,運(yùn)算符為”%“ | 
| ( | 左括號 | 用于混合運(yùn)算,限制優(yōu)先級 | 
| ) | 右括號 | 用于混合運(yùn)算,限制優(yōu)先級 | 
| Rad/Deg | 規(guī)定三角函數(shù)計(jì)算時(shí)的單位 | 按鍵顯示Rad代表使用弧度單位,按鍵顯示Deg代表使用角度單位 | 
| 2nd | 切換按鍵的第二功能 | 點(diǎn)擊該按鍵,三角函數(shù)切換為反三角函數(shù),指數(shù)和對數(shù)功能按鍵也會進(jìn)行轉(zhuǎn)換 | 
| sin | 計(jì)算正弦函數(shù) | 根據(jù)Rad/Deg按鍵輸入對應(yīng)單位的參數(shù),點(diǎn)擊該鍵直接計(jì)算結(jié)果 | 
| cos | 計(jì)算余弦函數(shù) | 根據(jù)Rad/Deg按鍵輸入對應(yīng)單位的參數(shù),點(diǎn)擊該鍵直接計(jì)算結(jié)果 | 
| tan | 計(jì)算正切函數(shù) | 根據(jù)Rad/Deg按鍵輸入對應(yīng)單位的參數(shù),點(diǎn)擊該鍵直接計(jì)算結(jié)果 | 
| asin | 計(jì)算反正弦函數(shù) | 輸入?yún)?shù),點(diǎn)擊該鍵根據(jù)Rad/Deg按鍵計(jì)算對應(yīng)單位的結(jié)果 | 
| acos | 計(jì)算反余弦函數(shù) | 輸入?yún)?shù),點(diǎn)擊該鍵根據(jù)Rad/Deg按鍵計(jì)算對應(yīng)單位的結(jié)果 | 
| atan | 計(jì)算反正切函數(shù) | 輸入?yún)?shù),點(diǎn)擊該鍵根據(jù)Rad/Deg按鍵計(jì)算對應(yīng)單位的結(jié)果 | 
| 2√x | 平方根 | 輸入?yún)?shù),點(diǎn)擊該按鍵直接計(jì)算結(jié)果 | 
| 3√x | 立方根 | 輸入?yún)?shù),點(diǎn)擊該按鍵直接計(jì)算結(jié)果 | 
| x^2 | 平方 | 輸入?yún)?shù),點(diǎn)擊該按鍵直接計(jì)算結(jié)果 | 
| x^3 | 立方 | 輸入?yún)?shù),點(diǎn)擊該按鍵直接計(jì)算結(jié)果 | 
| x^n | n次方 | 先輸入x,點(diǎn)擊該鍵,再輸入n,點(diǎn)擊“=”計(jì)算結(jié)果,可用于混合運(yùn)算。 | 
| n√x | n次根下x | 先輸入n,點(diǎn)擊該鍵,再輸入x,點(diǎn)擊“=”計(jì)算結(jié)果,可用于混合運(yùn)算。 | 
| log | 計(jì)算以10為底的對數(shù) | 輸入?yún)?shù),點(diǎn)擊該按鍵直接計(jì)算結(jié)果。 | 
| ylogx | 以x為底y的對數(shù) | 先輸入y,點(diǎn)擊該鍵,再輸入x,點(diǎn)擊“=”計(jì)算結(jié)果,可用于混合運(yùn)算。 | 
| ln | 計(jì)算以e為底的對數(shù) | 輸入?yún)?shù),點(diǎn)擊該按鍵直接計(jì)算結(jié)果。 | 
| e^x | e的x次方 | 輸入?yún)?shù),點(diǎn)擊該按鍵直接計(jì)算結(jié)果。 | 
| π | 圓周率 | 點(diǎn)擊該鍵顯示圓周率π的數(shù)值,該數(shù)值精度與設(shè)置精度有關(guān)。 | 
| e | 自然常數(shù)e | 點(diǎn)擊該鍵顯示自然常數(shù)e的數(shù)值,該數(shù)值精度與設(shè)置精度有關(guān)。 | 
| 1/x | 倒數(shù) | 輸入?yún)?shù),點(diǎn)擊該鍵直接計(jì)算結(jié)果。 | 
運(yùn)算結(jié)果精度說明:
程序中使用Java的BigDecimal類實(shí)現(xiàn)高精度,BigDecimal類中自帶加法add()、減法subtract()、乘法multiply()、除法**divide()及整數(shù)次方pow()**函數(shù)。
在上述函數(shù)基礎(chǔ)上自己實(shí)現(xiàn)對數(shù)函數(shù)log()、指數(shù)函數(shù)pow()、三角函數(shù)sin()、cos()、tan()、arcsin()、arccos()、arctan()、**arccot()**函數(shù),同樣可以達(dá)到無限精度。
步驟:
-  首先實(shí)現(xiàn)階乘函數(shù) public BigDecimal fac(int n)
-  ln(x)的泰勒展開為: 
 ln?(x)=ln?(1+y1?y)=2y(11+13y2+15y4+17y6+19y8+?)\ln (x)=\ln \left(\frac{1+y}{1-y}\right) \quad=2 y\left(\frac{1}{1}+\frac{1}{3} y^{2}+\frac{1}{5} y^{4}+\frac{1}{7} y^{6}+\frac{1}{9} y^{8}+\cdots\right) ln(x)=ln(1?y1+y?)=2y(11?+31?y2+51?y4+71?y6+91?y8+?)
 其中y = (x - 1) / (x + 1)在循環(huán)中不斷累加,如果當(dāng)前項(xiàng)的值小于設(shè)定精度,默認(rèn)小于10^-32時(shí)退出。 但該展開式只有在x接近1時(shí)收斂比較快,如果計(jì)算ln(10)經(jīng)測試大概耗時(shí)3s,完全不能忍。 接下來通過放縮區(qū)間加快速度,已知ln(xy)=ln(x)+ln(y),找一個(gè)折中的辦法,先將參數(shù)x 10倍放縮到[0.5, 5]區(qū)間,標(biāo)記縮放次數(shù)為ln10Count,再將參數(shù)x 1.1倍縮放到[0.95, 1.05]區(qū)間得到x’,標(biāo)記縮放次數(shù)為ln1_1Count,最終結(jié)果為ln10Count*ln(10) + ln1_1Count*ln(1.1) + ln(x’),該方法需要提前計(jì)算ln(10)與ln(1.1),但計(jì)算一次可以永久使用,對于ln(10)轉(zhuǎn)化為10*ln(1.25) + ln(1.073741824)進(jìn)一步加快速度。 
-  y log x即以x為底y的對數(shù)可轉(zhuǎn)換為log(y)/log(x) 
-  a^x的泰勒展開式為: 
 ax=exln?a=1+xln?a1!+(xln?a)22!+(xln?a)33!+?a^{x}=e^{x \ln a}=1+\frac{x \ln a}{1 !}+\frac{(x \ln a)^{2}}{2 !}+\frac{(x \ln a)^{3}}{3 !}+\cdots ax=exlna=1+1!xlna?+2!(xlna)2?+3!(xlna)3?+?
 其中需要前面實(shí)現(xiàn)的ln(x)
-  sin(x)的泰勒展開式為: 
 sin?x=∑n=0∞(?1)n(2n+1)!x2n+1=x?13!x3+15!x5??+(?1)n(2n+1)!x2n+1+?\sin x=\sum_{n=0}^{\infty} \frac{(-1)^{n}}{(2 n+1) !} x^{2 n+1}=x-\frac{1}{3 !} x^{3}+\frac{1}{5 !} x^{5}-\cdots+\frac{(-1)^{n}}{(2 n+1) !} x^{2 n+1}+\cdots sinx=n=0∑∞?(2n+1)!(?1)n?x2n+1=x?3!1?x3+5!1?x5??+(2n+1)!(?1)n?x2n+1+?
 該展開式只能計(jì)算[0, PI/2]區(qū)間的sin(x)的值,需要先將參數(shù)轉(zhuǎn)換到此區(qū)間
-  cos(x)同理 
-  tan(x) = sin(x)/cos(x) 
-  arctan(x)的泰勒展開式為: 
 arctan?x=∑n=0∞(?1)n2n+1x2n+1=x?13x3+15x5+?+(?1)n2n+1x2n+1+?\arctan x=\sum_{n=0}^{\infty} \frac{(-1)^{n}}{2 n+1} x^{2 n+1}=x-\frac{1}{3} x^{3}+\frac{1}{5} x^{5}+\cdots+\frac{(-1)^{n}}{2 n+1} x^{2 n+1}+\cdots arctanx=n=0∑∞?2n+1(?1)n?x2n+1=x?31?x3+51?x5+?+2n+1(?1)n?x2n+1+?
 x定義域?yàn)閷?shí)數(shù)集,但|x|在接近1或大于1的時(shí)候收斂速度特別慢解決辦法: 
- 使用arctan(-x) = -arctan(x),將參數(shù)限制到正實(shí)數(shù)
- 如果x>1,根據(jù)arctan(x)=PI/2-arctan(1/x),求arctan(1/x),將參數(shù)轉(zhuǎn)換到[0, 1]區(qū)間
- 但x在接近1時(shí)(如0.99)收斂仍然很慢,接下來將參數(shù)x限制到[0, 0.5]區(qū)間
- 如果x>0.5,根據(jù)arctan(x)=arctan(y)+arctan((x-y)/(1+xy)),將arctan的參數(shù)限制到0.5以下,此處可以選更小的值達(dá)到更快的速度
-  arccot(x) = PI/2 - arctan(x) 
-  arcsin(x) = arctan(x/sqrt(1-x^2)) 
-  arccos(x) = PI/2 - arcsin(x) 
混合運(yùn)算實(shí)現(xiàn)流程:
-  使用正則表達(dá)式提取輸入算式的參數(shù)和運(yùn)算符 用于匹配的正則表達(dá)式: 
 
-  將中綴表達(dá)式轉(zhuǎn)為后綴表達(dá)式 
-  對后綴表達(dá)式進(jìn)行計(jì)算 
更新日志:
-  2020.12.8 20.18 三角函數(shù)仍使用double進(jìn)行計(jì)算,精確到小數(shù)點(diǎn)后(16-整數(shù)位數(shù))位(如計(jì)算atan(80°)=89.28384005452959,即小數(shù)位數(shù)為16-2位整數(shù)位=14位小數(shù)位),相當(dāng)于對double變量表示不了的精度取了個(gè)近似值,計(jì)算結(jié)果不會再出現(xiàn)sin(30°) =0.49999999999999994這種情況。 
-  2020.12.10 16.12 正則表達(dá)式進(jìn)行了優(yōu)化,加入正后顧可以正確匹配負(fù)數(shù)和減法,比如對于“2-3”匹配結(jié)果應(yīng)該為(“2”,“-”,“3”),對于“-2–3”匹配結(jié)果應(yīng)該為(“-2”,“-”,“-3”)。 
-  2020.12.10 16.12 對數(shù)函數(shù)仍使用double進(jìn)行計(jì)算,使用與三角函數(shù)相同的方法解決精度問題。 
-  2020.12.11 10.46 結(jié)果使用DecimalFormat.format()格式化字符串,三位一體使用“,”分開顯示,但輸入?yún)?shù)還沒有實(shí)現(xiàn),如果要實(shí)現(xiàn)的話必須要跟win10計(jì)算器一樣當(dāng)參數(shù)輸入完畢,輸入運(yùn)算符時(shí)參數(shù)才上移。 
-  2020.12.14 19.07 使用BigDecimal實(shí)現(xiàn)常用數(shù)學(xué)函數(shù),可以達(dá)到無限精度 輸出結(jié)果三位一體分隔開,便于閱讀,輸入暫未實(shí)現(xiàn) 
待優(yōu)化功能:
- 將輸入?yún)?shù)和計(jì)算結(jié)果三位一體使用“,”分隔開,便于閱讀,可以使用DecimalFormat.format()函數(shù)。
- 三角函數(shù)應(yīng)該有角度制、弧度制、百分度制(梯度制),暫未實(shí)現(xiàn)百分度制。
- 使用BigDecimal實(shí)現(xiàn)對數(shù)函數(shù)及指數(shù)函數(shù)求解(log,ln,√,^),這樣可以達(dá)到任意精度,不再局限于double的精度。
- 計(jì)算前檢查算式的合法性,直接用規(guī)則檢查比較復(fù)雜,可以在混合運(yùn)算解析的過程中使用try和catch捕獲異常,對其他非混合運(yùn)算算式可直接檢查。比如檢查反三角函數(shù)的輸入?yún)?shù)范圍可以直接用規(guī)則檢查,檢查階乘的參數(shù)是不是整數(shù)二者都可以。
現(xiàn)對數(shù)函數(shù)及指數(shù)函數(shù)求解(log,ln,√,^),這樣可以達(dá)到任意精度,不再局限于double的精度。~~
- 計(jì)算前檢查算式的合法性,直接用規(guī)則檢查比較復(fù)雜,可以在混合運(yùn)算解析的過程中使用try和catch捕獲異常,對其他非混合運(yùn)算算式可直接檢查。比如檢查反三角函數(shù)的輸入?yún)?shù)范圍可以直接用規(guī)則檢查,檢查階乘的參數(shù)是不是整數(shù)二者都可以。
這個(gè)計(jì)算器也是匆匆趕時(shí)間完成的,再加上不可能考慮到所有輸入情況,沒有對錯誤的輸入進(jìn)行提示,其中肯定存在不少問題,項(xiàng)目地址在下面,其中包括4個(gè)java文件,CalculatorHMI實(shí)現(xiàn)計(jì)算器的圖形界面及按鍵的事件處理,修改其中的accuracy變量可以改變精度,也就是結(jié)果精確到小數(shù)點(diǎn)后多少位,默認(rèn)為32位,更高的位數(shù)也可以,但計(jì)算時(shí)間也會加長。BigDecimalMath就是用泰勒公式重寫的Math庫中的函數(shù),MixedOperation實(shí)現(xiàn)混合運(yùn)算,Main文件中就是主函數(shù),是整個(gè)工程的入口。當(dāng)然電腦上必須有jre也就是java運(yùn)行環(huán)境才可以運(yùn)行。
項(xiàng)目視頻
 github地址
------故里草木深------
總結(jié)
以上是生活随笔為你收集整理的使用Java实现的高精度科学计算器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: C语言isupper,tolower,i
- 下一篇: C语言函数介绍
