主頁 > 前端設計 > 計算器專案

計算器專案

2021-01-24 22:14:12 前端設計

專案簡介

本專案目的是寫一個計算器專案,主要考察演算法(堆疊、后綴運算式)和基本的HTML DOM,JavaScript的應用,本專案的基本架構是SpringBoot+Thymeleaf+Ajax,本專案由五個計算器組成:第一個是商務計算器,主要實作加減乘除的連續運算,沒有優先級,給出第一個運算元,按下運算子,清空輸入欄,然后輸入第二個運算元,按下等于會顯示結果;第二個是四則計算器,涉及到帶有優先級的運算,能夠實作一個帶括號的四則運算式的運算;第三個是科學計算器,就是在四則計算器的基礎上添加了三角、反三角、指數運算;第四個是貸款計算器,可以由兩種方式(等額本金和等額本息,具體計算公式請百度)計算每月還款等資料;第五個是進制轉換計算器,可以實作二進制、八進制、十進制、十六進制之間的相互轉化,
以下內容僅包括演算法決議,代碼中已經添加了足夠的注釋,具體專案原始碼請訪問GitHub:
https://github.com/Nown1/calculator

商務計算器

商務計算器(business.html)主要完成加減乘除的連續運算,例如輸入25,*,2,=會輸出50,接著按 *,2 會輸出100;演算法:首先用HTML DOM拼運算元,這里我用了一個p標簽來記錄輸入的數字,每按下一個數字就把這個數字拼接上,p.innerHTML += obj.value;當按下運算子,要把第一個運算元字串保存到res里面,同時保存運算子,將p標簽內容清空,然后繼續輸入數字,之后按下等于號時開始計算,首先把第二個運算元記錄下來,由于之前我們記錄了運算子和第一個運算元,只要進行運算即可,比如第一個運算元是res=“25”,即result=25.0;按下運算子operator=‘ * ‘,第二個運算元是num=“2”,即number=2.0;然后進行計算,result+=number,所以result==50.0,然后顯示在p標簽內,如果要繼續運算,按下運算子就會把之前的運算子替換掉,結果仍然保存在result里面,然后繼續輸入數字會保存在num里面,然后就可以再次運算,清零按鈕注意要把result一并清除,退格按鈕只要截取p標簽里面的內容,代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>商務計算器</title>
    <style>
        body{
            background-image: url("../img/2.jpg");
            background-repeat: no-repeat;
            background-position: center;
            background-size: cover;
        }
        .panel {
            /*定義面板*/
            border: 4px solid #ddd;
            width: 440px;
            height: 420px;
            margin:  auto;
            /*border-radius: 6px;*/
        }
        .panel p, .panel input {
            /*定義字體*/
            font-family: "微軟雅黑";
            font-size: 20px;
            margin: 4px;
            float: left;
            /*border-radius: 4px;*/
        }
        .panel p {
            /*定義輸入框*/
            width: 410px;
            height: 26px;
            border: 1px solid #ddd;
            padding: 6px;
            overflow: hidden;
        }
        .panel input {
            /*按鈕大小*/
            width: 100px;
            height: 50px;
            border:1px solid #ddd;
            align-content: center;
        }
    </style>
    <script>
        window.onload = function (){
            //獲取事件目標節點(整個div)
            var div = document.getElementById("jsq");
            //給事件目標節點后系結事件
            var num="0";//記錄運算元
            var res="0";//記錄結果
            var operator=" ";//記錄運算子
            var p=document.getElementById("screen");//獲取顯示屏

            function calculate(){//執行計算操作
                //1.將 "0"+螢屏顯示的數字先存到num里面,
                //2.把num,res分別化為float數number,result
                //3.執行運算
                num="0"+p.innerHTML;
                var number =parseFloat(num);
                var result=parseFloat(res);
                if(operator=="+"){
                    result+=number;
                    operator="";
                }else if(operator=="-"){
                    result-=number;
                    operator="";
                }else if(operator=="*"){
                    result*=number;
                    operator="";
                }else if(operator=="/"){
                    if(number==0){
                        result="Error";
                        operator="";
                    }
                    result/=number;
                    operator="";
                }else {
                    result=number;
                    operator="";
                }
                // alert(num+";"+number+";"+res+";"+result+";"+operator);
                return result;
            }
            function setOperator(a){//置運算子
                //需要執行:1.將符號復制給operator變數
                // 2.將 "0"+顯示屏字串 賦值給res
                // 3.將顯示屏清空
                operator=a;
                res="0"+p.innerHTML;
                p.innerHTML="";
            }
            function clear(){//清零方法
                p.innerHTML="";
                num="0";
                res="0";
            }
            function back(){//退格方法
                p.innerHTML=p.innerHTML.slice(0,p.innerHTML.length-1);
            }
            function setStr(a){//置數方法,需要執行以下步驟:
                //1.將
                p.innerHTML+=a;
            }
            div.onclick = function (e){
                //獲取事件源
                var obj = e.srcElement||e.target;
                //獲取顯示屏
                // var p = document.getElementById("screen");
                //若用戶點擊的區域是input便執行以下方法
                if(obj.nodeName=="INPUT"){
                    if(obj.value=="C"){
                        // p.innerHTML = "";
                        clear();
                    }else if(obj.value=="DEL"){
                        // p.innerHTML=p.innerHTML.slice(0,p.innerHTML.length-1)
                        back();
                    }else if(obj.value=="="){
                            p.innerHTML = calculate().toString();
                    }else if(obj.value=="+"||obj.value=="-"||obj.value=="*"||obj.value=="/"){
                        setOperator(obj.value);
                    }else{
                        p.innerHTML += obj.value;
                    }
                }
            }
        }
    </script>
</head>
<body>

<form action="/">
    <a href="/Business">商務計算器</a><br/>
    <a href="/Simple" >四則計算器</a><br/>
    <a href="/Science">科學計算器</a><br/>
    <a href="/Loan">貸款計算器</a><br/>
    <a href="/Base">進制計算器</a>
</form>

<div class="panel" id="jsq">
    <div>
        <h3 align="center">商務計算器</h3>
        <hr>
        <p id="screen"></p>
        <input type="button" value="C" οnclick="clear()">
        <input type="button" value="DEL" οnclick="back()">
        <div style="clear:both"></div>
    </div>
    <div>
        <input type="button" value="7">
        <input type="button" value="8">
        <input type="button" value="9">
        <input type="button" value="/">

        <input type="button" value="4" >
        <input type="button" value="5" >
        <input type="button" value="6" >
        <input type="button" value="*" >

        <input type="button" value="1" >
        <input type="button" value="2" >
        <input type="button" value="3" >
        <input type="button" value="-">

        <input type="button" value="0" >
        <input type="button" value="." >
        <input type="button" value="=">
        <input type="button" value="+">

        <div style="clear:both"></div>
    </div>
</div>
</body>
</html>

四則計算器

四則計算器(simple.html)要涉及到優先級運算,要用到后綴運算式,堆疊,因此我并沒有用JavaScript寫演算法,而是用Java,在程式運行時,前端只要關注如何把運算式傳到后端,后端進行運算,并將結果發送到前端,既然涉及到不重繪頁面的訪問請求,所以用到了Ajax異步請求,在向后端發送請求時,遇到了一個問題,就是由于編碼問題,某些字符,如+、-、*、/等傳到后端就消失了,因此這里又進行了強制編碼var url="/Simple?question=" +encodeURI(encodeURIComponent(p.innerHTML)); 后端在接受請求時需要解碼String q=java.net.URLDecoder.decode(question,"UTF-8"); ,注意用try-catch陳述句捕獲例外,前端關鍵代碼如下:

<script>

        window.onload = function () {
            //獲取事件目標節點(整個div)
            var div = document.getElementById("jsq");
            //獲取輸入欄
            var p=document.getElementById("question");
            //獲取答案欄
            var q=document.getElementById("answer");
            var ans;


            //使用Ajax發送異步請求獲取結果并修改答案欄文字
            function calculate()
            {
                var xmlhttp;
                if (window.XMLHttpRequest)
                {
                    // IE7+, Firefox, Chrome, Opera, Safari 瀏覽器執行代碼
                    xmlhttp=new XMLHttpRequest();
                }
                else
                {
                    // IE6, IE5 瀏覽器執行代碼
                    xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
                }
                xmlhttp.onreadystatechange=function()
                {
                    if (xmlhttp.readyState==4 && xmlhttp.status==200)
                    {
                        q.innerHTML=xmlhttp.responseText;
                    }
                }

                //直接令url="/Simple?question=" +p.innerHTML 會導致url中部分字符丟失,比如+ -
                //使用encodeURI(encodeURIComponent(url))方法可以將url轉化為utf-8編碼形式,
                //用%2F代替/,用%2B代替+,但是在請求服務器的時候,請求路徑前面必須是/,
                //因此只要把p.innerHTML進行編碼即可,然后和請求路徑拼接起來
                //后端接受到的資料是utf-8編碼的,因此還要進行解碼
                //方法是:String q=java.net.URLDecoder.decode(question,"UTF-8");
                //注意用try-catch捕獲例外

                var url="/Simple?question=" +encodeURI(encodeURIComponent(p.innerHTML));
                xmlhttp.open("POST",url,true);
                xmlhttp.send();
            }
            div.onclick = function (e){
                //獲取事件源
                var obj = e.srcElement||e.target;
                //若用戶點擊的區域是input便執行以下方法
                if(obj.nodeName=="INPUT"){
                    if(obj.value=="C"){
                        p.innerHTML = "";
                        q.innerHTML="";
                    }else if (obj.value=="M"){
                        ans=q.innerHTML;
                    }else if (obj.value=="ans"){
                        p.innerHTML=ans;
                    }

                    else if(obj.value=="DEL"){
                        p.innerHTML=p.innerHTML.slice(0,p.innerHTML.length-1)
                    }else if(obj.value=="="){
                       calculate();
                    }else{
                        p.innerHTML += obj.value;
                    }
                }
            }
        }
    </script>

后端我是用Java寫的演算法,我們先來學習一下演算法的知識:
本演算法涉及堆疊(先進后出,后進先出)的結構,由于Java是有多種資料型別的,所以我設計了兩個堆疊,一個元素型別是char,用于存放運算子,一個元素型別是double,用于存放資料,當然,會泛型的朋友可以直接用泛型,我菜雞不說話,同時,在計算時要用到后綴運算式,例如1+((2+3)*4+7)+6/4換成后綴運算式應該是1,2,3,+,4,*,7,+,+,6,4,/,+,這樣在計算的時候如果是數字先保存,遇到運算子就取出堆疊頂兩個數字進行一次運算,然后將結果再壓入堆疊內,計算程序如下:

1		//遇到數字,直接進堆疊
1,2		//遇到數字,直接進堆疊
1,2,3		//遇到數字,直接進堆疊
1,5	//遇到加號,取出堆疊頂兩個數進行加法運算,2+3=5,將5進堆疊
1,5,4		//遇到數字,直接進堆疊
1,20	//遇到*,取出堆疊頂兩個數進行乘法運算,5*4=20,將20進堆疊
1,20,7	//遇到數字,直接進堆疊
1,27	//遇到+,取出堆疊頂兩個數進行加法運算,20+7=27,將27進堆疊
28	//遇到+,取出堆疊頂兩個數進行加法運算,1+27=28,將28進堆疊
28,6	//遇到數字,直接進堆疊
28,6,4	//遇到數字,直接進堆疊
28,6,4	//遇到/,取出堆疊頂兩個數進行除法運算,6/4=1.5,將1.5進堆疊
28,1.5 //遇到+,取出堆疊頂兩個數,28+1.5=29.5,將29.5進堆疊
29.5//計算結束,數字堆疊內堆疊頂元素就是結果

那么,在得到后綴運算式的時候,什么時候讓運算子進堆疊,什么時候出堆疊呢?這就要考慮優先級,如果要進堆疊運算子優先級高就進堆疊,否則取出堆疊頂運算子執行運算,直到把這個運算子放進去

先來個簡單的,對于1+2+3,我們是直接從左到右進行運算的,數字1記下,第一個運算子加號入堆疊,數字2記下,又遇到加號,我們希望先把前面兩個數加起來,因此要先把堆疊內的加號取出來記錄,也就是進行了一次加法運算,然后把第二個加號入堆疊,數字3記下,遍歷結束,把堆疊內的加號取出來補上,就是1,2,+,3,+

對于1+2*3,數字1先記下,然后第一個運算子+先進堆疊,數字2記下,碰到乘號,我們并不想讓前兩個數進行運算,而是讓乘號進堆疊,然后將3取出,遍歷結束,再把運算子從堆疊內取出補上,得到了1,2,3,*,+(加號先進堆疊,所以后出來)

對于2*3+1,數字2記下,然后第一個乘號入堆疊,然后數字3記下,遇到加號,我們希望2和3相乘,所以先把堆疊內的乘號取出來,之后再把加號放入堆疊內,然后再把1記下,最后把堆疊內的運算子取出來補上,就得到了2,3,*,+

如果有括號,比如1+(2+3)* 6,第一個數1記下,第一個運算子加號進堆疊,左括號先進堆疊,數字2記下,我們不希望1和2相加,因此讓加號進堆疊,數字3記下,遇到右括號,我們希望先把括號內的算完,所以先把堆疊頂的加號取出來,也就是先把堆疊頂的2和3進行了一次加法運算,然后堆疊頂元素是左括號,我們就把左括號取出,右括號至此處理完畢,此時堆疊頂元素是加號,遇到乘號,先把乘號進堆疊,數字6取出來,然后把堆疊內的運算子都取出來,得到的就是1,2,3,+,6,*,+

由此可見,堆疊內的加號(或減號)優先級比堆疊外的加號(或減號)優先級高,比堆疊外的乘號(或除號)優先級低;堆疊內的乘號(或除號)優先級比堆疊外的加號(或減號)優先級高,比堆疊外的乘號(或除號)優先級高,堆疊外的左括號優先級最高,但是一旦進堆疊就成為最低,比堆疊外加號優先級還低,堆疊外的右括號優先級最低,比堆疊內的加號優先級還低,為了便于判斷什么時候堆疊外的右括號和堆疊內的左括號匹配,我們應該讓兩者優先級相等,同時,為了便于對運算子堆疊進行初始化,我們先讓 # 進堆疊,代表最低優先級的運算子,如果用int icp(char operator)函式回傳堆疊外運算子operator的優先級,用 int isp(char operator)函式回傳堆疊內運算子優先級,則有以下關系:

icp(#)<icp( 右括號 )=isp(左括號)<icp(+)=icp(-)<isp(+)<isp(-)<icp(*)<icp(/)<isp(*)=isp(/)<icp(左括號)

注意堆疊外的右括號是不可能進堆疊的,它的作用僅限于將堆疊內匹配的左括號移除,代碼實作如下:

public int isp(char ch) {//判斷站內運算子優先級
        switch (ch) {
            case '#':
                return 0;
            case '(':
                return 1;
            case '*':
            case '/':
                return 5;
            case '+':
            case '-':
                return 3;
            default:
                return -1;
        }
    }

    public int icp(char ch) {//判斷要進站運算子優先級
        switch (ch) {
            case '#':
                return 0;
            case '(':
                return 6;
            case '*':
            case '/':
                return 4;
            case '+':
            case '-':
                return 2;
            case ')':
                return 1;
            default:
                return -1;
        }
    }

如果轉后綴運算式再計算,需要把數字和運算子都以String的形式存到一個String陣列里面,而不是簡單拼接,因為簡單拼接你不知道后綴運算式中相鄰兩個數字在哪里分開,舉個簡單例子,1+(2+3)* 6后綴運算式是 1,2,3,+,6,*,+,如果直接拼接就是 123+6*+,第一個數字123嘛?!而如果存到陣列里面還要進行第二次遍歷,時間復雜度會大一點,所以在實際演算法中,我并不是先的到后綴運算式然后再計算,而是在遍歷程序中就開始計算,基本思想是:

如果是一個數字,我就保存起來,如果是運算子,如果要進堆疊的運算子優先級高則進堆疊,如果要進堆疊的運算子優先級低就取出數字堆疊堆疊頂兩個數字和運算子堆疊堆疊頂一個運算子進行運算,將結果壓入數字堆疊內,直到這個運算子進堆疊,或者右括號找到與之匹配的左括號,

先對運算式字串進行遍歷,用ch代表字串中某個字符,用String型別的number來存數字,考慮到有負數運算,先讓number=“0”,用boolean型別的notComplete判斷是否已經將運算子處理好,每次默認為true,如果是0~9的數字或者小數點就直接和number拼接即可,也就是number=number+ch,如果是運算子,需要先把number代表的數字存到數字堆疊內,然后判斷優先級,如果ch優先級高則進堆疊,同時再把number復位,complete=false跳出回圈,如果ch低則要進行運算,直到入堆疊,如果是右括號,則直到找到堆疊內對應的左括號,然后將notComplete=false,

你以為這就完了?大意了!

如果只要不是數字或小數點就把number壓入堆疊內,當碰到左括號或者右括號后面的運算子(如果有的話)就會錯誤的把0壓入堆疊內,比如2*(2+3),遇到乘號時就把2進堆疊,number=“0”了,當又遇到乘號時,會誤把0入堆疊;或者(1+2)+3,遇到右括號時2入堆疊,然后number=“0”,當又遇到+號時又把0進堆疊了,因此要對這兩個符號分開處理,如果是左括號只要進堆疊就好了,不要再把number壓入數字堆疊,如果是右括號,則將number壓入堆疊內,然后和堆疊頂元素比較優先級,直到找到對應的左括號,將之移除,處理完右括號,還要再處理右括號后面的運算子,如果此右括號是運算式最后一個字符,就結束了;如果不是,則要對右括號后面的運算子提前進行處理,因此我又引入了一個Boolean型別的flag變數,功能和notComplete類似,然而這也還沒完,因為雖然運算式遍歷完了,但是運算子堆疊內可能還有運算子,因此還要執行一些運算操作,只要運算子堆疊不空就取出堆疊頂元素和數字堆疊內兩個數字進行運算,

年輕人,是不是草率了?

理論上講,我的代碼沒有問題,可是你給我的運算式可能會有問題,比如你給我一個0…2,或者1/0,或者1+2(2-3)是什么意思?第一個這么多小數點干嘛?害得我在轉double值的時候可能會出錯;第二個分母為零;第三個括號前沒有運算子,你說是乘號給省略了,呵呵,我不認,年輕人不講碼德!因此我又用try-catch陳述句捕獲了一下例外,
在這里插入圖片描述
為了便于追蹤計算的每個步驟,我在執行入堆疊和出堆疊方法時都會輸出一下是第幾個元素,哪個元素進堆疊或者出堆疊了,在遍歷結束后會輸出 “遍歷結束”,在執行運算時會輸出執行了什么運算,

巴巴了這么多,嘴類,手累,代碼才是最好的溝通語言,不說了,上代碼!

代碼展示

運算子堆疊(CharStack.java):

package com.nown.utils;

public class CharStack {
    private int top;
    private char[] elements;
    public CharStack(int size){
        top=-1;
        elements=new char[size];
    }
    public char remove(){//退堆疊方法,從堆疊中取出堆疊頂元素并移除
        System.out.println("將第"+top+"個運算子"+elements[top]+"移除運算子堆疊");
        return elements[top--];
    }
    public char pop(){//顯示堆疊頂元素,只顯示而不移除
        return elements[top];
    }
    public void add(char value){
        System.out.println("第"+(top+1)+"個入堆疊的運算子是"+value);
        elements[++top]=value;
    }
    public boolean isEmpty(){
        return top==0;
    }
}

數字堆疊(DoubleStack.java):

package com.nown.utils;

public class DoubleStack {
    private int top;
    private double[] elements;
    public DoubleStack(int size){
        top=-1;
        elements=new double[size];
    }
    public double remove(){
        System.out.println("將第"+top+"個數字"+elements[top]+"移除數字堆疊");
        return elements[top--];
    }
    public void add(double value){
        System.out.println("第"+(top+1)+"個入堆疊的數字是"+value);
        elements[++top]=value;
    }
    public boolean isEmpty(){
        return top==0;
    }
}

簡單計算器類 (SimpleCaculator):Too easy too simple

package com.nown.utils.calculator;

import com.nown.utils.CharStack;
import com.nown.utils.DoubleStack;

public class SimpleCalculator {
    private CharStack charStack;//字符堆疊,存放運算子
    private DoubleStack doubleStack;//數堆疊,存放運算子
    private char[] question;//字符陣列,將計算式轉化為charArray以便進行遍歷,
    int length;

    public SimpleCalculator(String question) {
        this.question = question.toCharArray();
        length = question.length();
        charStack = new CharStack(length);
        doubleStack = new DoubleStack(length);
        charStack.add('#');//先在運算子堆疊存放一個#代表最低優先級運算子
        doubleStack.add(0.0);//在數堆疊存放0進行初始化,防止"0.5"用".5"表示時報錯,同時也是為了負數運算
    }

    public String getAnswer() {
        int i = 0;
        String number = "0";//臨時存放數字,到運算子時則意味著這個數字結束,編程double值存到數堆疊
        boolean notComplete;//判斷有沒有將運算子壓入堆疊內
        try {
            for (;i<length;i++){
                char ch = question[i];
                notComplete=true;//沒有完成進堆疊操作?yes

                    if (ch == '(') {
                        //如果是左括號直接進堆疊即可
                        charStack.add(ch);
                        notComplete = false;
                    } else if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == ')') {
                        //如果是運算子或右括號
                        //先把number記錄的數字壓入數字堆疊,然后把number="0"進行初始化
                        double num = Double.parseDouble(number);
                        number = "0";
                        doubleStack.add(num);

                        while (notComplete) {
                            if (icp(ch) > isp(charStack.pop())) {
                                //如果要進堆疊的運算子優先級高
                                //則將數字進堆疊,運算子進堆疊
                                charStack.add(ch);
                                notComplete = false;//沒有完成壓堆疊操作?no,完成了
                            } else if (icp(ch) < isp(charStack.pop())) {
                                //如果要進堆疊運算子優先級低,則從堆疊中取出一個運算子和兩個運算元進行計算
                                //將結果壓入數字堆疊,然后接著判斷(不需要讓notComplete=false),直到該運算子進堆疊
                                char operator = charStack.remove();
                                double num1 = doubleStack.remove();
                                double num2 = doubleStack.remove();
                                double result = calculate(num2, num1, operator);
                                doubleStack.add(result);
                            } else {
                                //當要進堆疊的運算子優先級和堆疊頂元素優先級相等,
                                //則只可能是堆疊頂元素是左括號,要進堆疊元素是右括號
                                if (i == length - 1) {
                                    //如果此時右括號剛好是運算式最后一個字符,則只要將左括號移除
                                    charStack.remove();
                                    notComplete=false;
                                } else {
                                    //如果不是在運算式末尾,需要提前對右括號后面的運算子進行處理,
                                    //然后i++跳過后面的運算子
                                    //這樣做的目的是防止后面的運算子使數字堆疊多存入一個0
                                    charStack.remove();
                                    char operator = question[++i];
                                    boolean flag = true;//設定一個臨時變數判斷有沒有將右括號后面的運算子入堆疊

                                    while (flag) {
                                        if (icp(operator) > isp(charStack.pop())) {
                                            //如果該運算子優先級比較高,則直接入堆疊即可,操作結束
                                            charStack.add(operator);
                                            flag = false;
                                        } else {
                                            //如果該運算子優先級比較低,則取出一個運算子,兩個運算元進行運算,
                                            //然后接著判斷(先不讓flag=false),直到該運算子進堆疊
                                            char op=charStack.remove();
                                            double num1 = doubleStack.remove();
                                            double num2 = doubleStack.remove();
                                            double result = calculate(num2, num1, op);
                                            doubleStack.add(result);

                                        }
                                    }
                                    notComplete=false;
                                }
                            }
                        }

                    } else {
                        number += ch;
                    }

            }
        //整個算式已經遍歷完,但是最后一個數字可能還沒進堆疊,且字符堆疊內可能還有運算子,也就是說還沒有運算結束
        //如果最后一個字符是右括號,那么所有的數字都已經進堆疊了,
            // 不需要把最后的number="0"壓入堆疊內,否則需要壓入堆疊內
            if(question[length-1]!=')'){
                System.out.println("遍歷后將數字"+Double.parseDouble(number)+"壓入堆疊內");
                doubleStack.add(Double.parseDouble(number));
            }
            System.out.println("完成遍歷");

        while (!charStack.isEmpty()) {
            char operator = charStack.remove();
            double num1 = doubleStack.remove();
            double num2 = doubleStack.remove();
            double result=calculate(num2,num1,operator);
            doubleStack.add(result);
        }
    }catch( Exception e){
        return "錯誤";
    }

    double answer = doubleStack.remove();
        return""+answer;
}

    public double calculate(double num2,double num1,char operator) throws Exception{
        switch (operator){
            case '+':
                System.out.println("執行了一次加法:"+num2+"+"+num1);
                return num2+num1;
            case '-':
                System.out.println("執行了一次減法:"+num2+"-"+num1);
                return num2-num1;
            case '*':
                System.out.println("執行了一次乘法:"+num2+"*"+num1);
                return num2*num1;
            default:
                if (num1==0){
                    throw new Exception();
                }
                System.out.println("執行了一次除法:"+num2+"/"+num1);
                return num2/num1;
        }

    }

    public int isp(char ch) {//判斷站內運算子優先級
        switch (ch) {
            case '#':
                return 0;
            case '(':
                return 1;
            case '*':
            case '/':
                return 5;
            case '+':
            case '-':
                return 3;
            default:
                return -1;
        }
    }

    public int icp(char ch) {//判斷要進站運算子優先級
        switch (ch) {
            case '#':
                return 0;
            case '(':
                return 6;
            case '*':
            case '/':
            case '%':
                return 4;
            case '+':
            case '-':
                return 2;
            case ')':
                return 1;
            default:
                return -1;
        }
    }
}

計算器進階—科學計算器

以上代碼只是實作了四則運算,還有括號,但是我怎么會滿足呢?給爺敲!

于是,我在以上計算器基礎上又加入了三角,反三角,指數運算,其實主要是優先級的問題,還有就是啊,sin,cos,tan,arcsin,arccos,arctan都是單目運算子,它前面是沒有運算元的,而且運算的時候也只要取出一個運算元即可,其他的,理論上講,大同小異,優先級可以自己推導,我就不舉例說明了,有以下關系:

icp(#)<icp( 右括號 )=isp(左括號)<icp(+)=icp(-)<isp(+)<isp(-)<icp(*)<icp(/)<isp(*)=isp(/)<icp()=icp(sin)=icp(arcsin)<isp()=isp(sin)=isp(arcsin)<icp(左括號)

簡單來說就是,堆疊內堆疊外加減號優先級一致,乘除號優先級一致,指數,三角,反三角優先級一致,同一運算子,堆疊內的優先級高于堆疊外運算子一等,左括號變化最大,堆疊外優先級最高,而堆疊內優先級最低,為了便于匹配左右括號,我們讓堆疊內的左括號和堆疊外的右括號優先級一致,同時堆疊內不存在右括號,

然后對代碼進一步優化,上面的代碼每次在執行運算操作的時候都要從堆疊內remove一個運算子,兩個數字,多次重復,對于這個進階版科學計算器,還要涉及單目運算子,只有一個運算元,如果每次都在getAnswer()方法中進行判斷必定會出現大量重復代碼,這我能忍?盤它!

代碼如下:

package com.nown.utils.calculator;

import com.nown.utils.CharStack;
import com.nown.utils.DoubleStack;

public class ScienceCalculator {
    private CharStack charStack;//字符堆疊,存放運算子
    private DoubleStack doubleStack;//數堆疊,存放運算子
    private String question;//字符陣列,將計算式轉化為charArray,
    int length;

    public ScienceCalculator(String question) {
        this.question = question;
        length = question.length();
        charStack = new CharStack(length);
        doubleStack = new DoubleStack(length);
        charStack.add('#');//先在運算子堆疊存放一個#代表最低優先級運算子
        doubleStack.add(0.0);//在數堆疊存放0進行初始化,防止"0.5"用".5"表示時報錯
    }

    public String getAnswer() {
        int i = 0;
        String number = "0";//臨時存放數字,到運算子時則意味著這個數字結束,編程double值存到數堆疊
        boolean notComplete;//判斷有沒有將運算子壓入堆疊內
        try {
            for (;i<length;i++){
                char ch = question.charAt(i);
                notComplete=true;//沒有完成進堆疊操作?yes

                if (ch == '('||ch=='s'||ch=='c'||ch=='t'||
                        ch=='i'||ch=='o'||ch=='n'||ch=='q'||ch=='a') {
                    //如果是左括號或者單目運算子直接進堆疊即可
                    charStack.add(ch);
                    notComplete = false;
                }
                else if ((ch>='0'&&ch<='9')||ch=='.'||ch=='p'){
                    //如果是數字則只要和number拼接即可
                    //如果是PI,則直接把"3.141...."賦值給number
                    if (ch=='p'){
                        number=Double.toString(Math.PI);
                    }else {
                        number += ch;
                    }

                }else {
                    //如果是雙目運算子或右括號
                    //先把number記錄的數字壓入數字堆疊,然后把number="0"進行初始化
                    double num = Double.parseDouble(number);
                    number = "0";
                    doubleStack.add(num);

                    while (notComplete) {
                        if (icp(ch) > isp(charStack.pop())) {
                            //如果要進堆疊的運算子優先級高
                            //則將數字進堆疊,運算子進堆疊
                            charStack.add(ch);
                            notComplete = false;//沒有完成壓堆疊操作?no,完成了
                        } else if (icp(ch) < isp(charStack.pop())) {
                            //如果要進堆疊運算子優先級低,則從堆疊中取出一個運算子和兩個運算元進行計算
                            //將結果壓入數字堆疊,然后接著判斷(不需要讓notComplete=false),直到該運算子進堆疊
                            double result = calculate();
                            doubleStack.add(result);
                        } else {
                            //當要進堆疊的運算子優先級和堆疊頂元素優先級相等,
                            //則只可能是堆疊頂元素是左括號,要進堆疊元素是右括號
                            if (i == length - 1) {
                                //如果此時右括號剛好是運算式最后一個字符,則只要將左括號移除
                                charStack.remove();
                                notComplete=false;
                            } else {
                                //如果不是在運算式末尾,需要提前對右括號后面的運算子進行處理,
                                //然后i++跳過后面的運算子
                                //這樣做的目的是防止后面的運算子使數字堆疊多存入一個0
                                charStack.remove();
                                char operator = question.charAt(++i);
                                boolean flag = true;//設定一個臨時變數判斷有沒有將右括號后面的運算子入堆疊

                                while (flag) {
                                    if (icp(operator) > isp(charStack.pop())) {
                                        //如果該運算子優先級比較高,則直接入堆疊即可,操作結束
                                        charStack.add(operator);
                                        flag = false;
                                    } else {
                                        //如果該運算子優先級比較低,則取出一個運算子,兩個運算元進行運算,
                                        //然后接著判斷(先不讓flag=false),直到該運算子進堆疊
                                        double result = calculate();
                                        doubleStack.add(result);

                                    }
                                }
                                notComplete=false;
                            }
                        }
                    }

                }

            }
            //整個算式已經遍歷完,但是最后一個數字可能還沒進堆疊,且字符堆疊內可能還有運算子,也就是說還沒有運算結束
            //如果最后一個字符是右括號,那么所有的數字都已經進堆疊了,
            // 不需要把最后的number="0"壓入堆疊內,否則需要壓入堆疊內
            if(question.charAt(length-1)!=')'){
                System.out.println("遍歷后將數字"+Double.parseDouble(number)+"壓入堆疊內");
                doubleStack.add(Double.parseDouble(number));
            }
            System.out.println("完成遍歷");

            while (!charStack.isEmpty()) {

                double result=calculate();
                doubleStack.add(result);
            }
        }catch( Exception e){
            return "錯誤";
        }

        double answer = doubleStack.remove();
        return""+answer;
    }

    public double calculate() throws  Exception{
        char operator=charStack.remove();
        if(operator=='^'||operator=='+'||operator=='-'||operator=='*'||operator=='/'){
            //雙目運算
            double num1=doubleStack.remove();
            double num2=doubleStack.remove();
            switch (operator){
                case '^':
                    System.out.println("執行了一次指數運算: "+num2+"^"+num1);
                    return Math.pow(num2,num1);
                case '+':
                    System.out.println("執行了一次加法:"+num2+"+"+num1);
                    return num2+num1;
                case '-':
                    System.out.println("執行了一次減法:"+num2+"-"+num1);
                    return num2-num1;
                case '*':
                    System.out.println("執行了一次乘法:"+num2+"*"+num1);
                    return num2*num1;
                case '/':
                    if (num1==0){
                        throw  new Exception();
                    }
                    System.out.println("執行了一次除法:"+num2+"/"+num1);
                    return num2/num1;
                default:
                    System.out.println("單目運算子非法");
                    return 0;
            }
        }else {
            //單目運算
            double num=doubleStack.remove();
            switch (operator){
                case 's':
                    System.out.println("執行一次求正弦操作:sin"+num);
                    return Math.sin(num);
                case 'c':
                    System.out.println("執行一次求余弦操作:cos"+num);
                    return Math.cos(num);
                case 't':
                    System.out.println("執行一次求正切操作:tan"+num);
                    return Math.tan(num);
                case 'a':
                    System.out.println("執行一次求絕對值操作:abs"+num);
                    return Math.abs(num);
                case 'i':
                    System.out.println("執行一次求角度操作:arcsin"+num);
                    return Math.asin(num);
                case 'o':
                    System.out.println("執行一次求角度操作:arccos"+num);
                    return Math.acos(num);
                case 'n':
                    System.out.println("執行一次求角度操作:arctan"+num);
                    return Math.atan(num);
                case 'q':
                    if (num<0){
                        throw new Exception();
                    }
                    System.out.println("執行一次開方操作:sqrt"+num);
                    return Math.sqrt(num);
                default:
                    return 0;
            }
        }


    }

    public int isp(char ch) {//判斷站內運算子優先級
        switch (ch) {
            case '#':
                return 0;
            case '(':
                return 1;
            case '+':
            case '-':
                return 3;
            case '*':
            case '/':
                return 5;
            case '^':
            case 's':
            case 'c':
            case 't':
            case 'i':
            case 'o':
            case 'n':
            case 'a':
            case 'q':
                return 7;
            case ')':
                return 8;
            default:
                return -1;
        }
    }

    public int icp(char ch) {//判斷要進站運算子優先級
        switch (ch) {
            case '#':
                return 0;
            case ')':
                return 1;
            case '+':
            case '-':
                return 2;
            case '*':
            case '/':
                return 4;
            case '^':
            case 's':
            case 'c':
            case 't':
            case 'i':
            case 'o':
            case 'n':
            case 'a':
            case 'q':
                return 6;
            default:
                return -1;
        }
    }
}

貸款計算器

該計算器比較簡單,只要知道公式,由HTML DOM操縱標簽內容即可,不做過多解釋,關鍵代碼如下:

<script>

        var method = "";

        function setMethod(obj) {
            method =""+ obj.value;
        }

        function calculate() {
            var principle = parseFloat(document.getElementById("principle").value);
            var months = parseFloat(document.getElementById("months").value);
            var rate = parseFloat(document.getElementById("rate").value);
            var repayment = document.getElementById("repayment");
            var interest = document.getElementById("interest");
            var totalRepayment = document.getElementById("totalRepayment");
            var totalInterest = document.getElementById("totalInterest");

            try{
                //資料預處理
                principle *= 10000;
                months *= 12;
                rate *= 0.01;

                if (method == "1") {
                    // alert("等額本息");
                    // alert("本金="+principle+"; 月數="+months+"; 利率="+rate);

                        //月均還款
                        var rep = (principle * rate * Math.pow(1 + rate, months)) / (Math.pow(1 + rate, months)-1);
                        repayment.innerHTML = rep.toFixed(2).toString();

                        //月均利息
                        var str = "";
                        var y=0;
                        for (var i = 1; i <=months; i++) {
                            y= principle * rate * (Math.pow(1 + rate, months) - Math.pow(1 + rate, i-1)) / (Math.pow(1 + rate, months)-1);
                            str += y.toFixed(2).toString() +",";
                        }
                        interest.innerHTML = str;

                        //還款總額
                        totalRepayment.innerHTML = (months * rep).toString();

                        //總利息
                        totalInterest.innerHTML=(months * rep-principle).toString();

                } else  {
                    // alert("等額本金");
                    // alert("本金="+principle+"; 月數="+months+"; 利率="+rate);

                        //月均還款
                        var paid=0;//累計已還款金額
                        var str1="";//記錄月均還款
                        var str2="";//記錄月均利息
                        var x=0;//月均還款
                        var y=0;//月均利息
                        var z=0;//總利息

                        for (var i=0;i<months;i++){
                            x=(principle/months)+(principle-paid)*rate;
                            str1+=x.toFixed(2).toString()+",";
                            y=(principle-paid)*rate;
                            str2+=y.toFixed(2).toString()+",";
                            paid+=y;
                        }
                        z=(((principle/months)+(principle*rate)+(principle*(1+rate)/months))/2)*months-principle;
                        //月均還款
                        repayment.innerHTML=str1;

                        //月均利息
                        interest.innerHTML=str2;

                        //還款總額
                        totalRepayment.innerHTML=paid.toFixed(2).toString();

                        //總利息
                        totalInterest.innerHTML=z;

                }

            }catch (e) {
            repayment.innerHTML = "錯誤";
            interest.innerHTML="錯誤";
            totalInterest.innerHTML = "錯誤";
            totalRepayment.innerHTML = "錯誤";
            }

        }

進制計算器

該計算器要實作二、八、十、十六進制的相互轉化,主要思路是,先寫一套十進制數轉二、八、十六進制的演算法,然后再寫一套二、八、十六轉十進制的演算法,這樣如果二轉八可以先由二進制轉十進制,然后由十進制轉八進制,關鍵代碼如下:

<script>
        var num1="10";
        var num2="10";

        function toBinary(a) {//二進制
            var bin="";
            a=parseInt(a);
            while(a!=0){
                bin=(a%2).toFixed()+bin;
                a=parseInt(a/2);
            }
            // alert(bin);
            return bin;
        }

        function toHex(a){//十六進制
            var hex="";
            a=parseInt(a);
            while(a!=0){
                if (a%16<10){
                    hex=(a%16).toFixed()+hex;
                }else if(a%16==10){
                    hex="A"+hex;
                }else if (a%16==11){
                    hex="B"+hex;
                }else if(a%16==12){
                    hex="C"+hex;
                }else if (a%16==13){
                    hex="D"+hex;
                }else if(a%16==14){
                    hex="E"+hex;
                }else {
                    hex="F"+hex;
                }
                a=parseInt(a/16);
            }
            // alert(hex);
            return hex;
        }

        function toOct(a) {//轉為八進制
            var oct="";
            a=parseInt(a);
            while(a!=0){
                oct=(a%8).toFixed()+oct;
                a=parseInt(a/8);
            }
            // alert(oct);
            return oct;
        }

        function binaryToDec(str) {//二進制轉為十進制
            str=str.toString();
            var n=1;
            var len=str.length;
            var dec=0;
            for(let i=len-1;i>=0;i--){
                var c=""+str.charAt(i);
                dec=Number(c)*n+dec;
                n*=2;
            }
            // alert(dec);
            return dec;
        }

        function octToDec(str) {//八進制轉十進制
            str=str.toString();
            var n=1;
            var len=str.length;
            var dec=0;
            for(let i=len-1;i>=0;i--){
                var c=""+str.charAt(i);
                dec=Number(c)*n+dec;
                n*=8;
            }
            // alert(dec);
            return dec;
        }

        function hexToDec(str){//十六進制轉十進制
            str=str.toString();
            var n=1;
            var len=str.length;
            var dec=0;
            var ch='';
            for(let i=len-1;i>=0;i--){
                ch=str.charAt(i);
                if (ch>='0'&&ch<='9'){
                    ch=""+ch;
                    dec=Number(ch)*n+dec;
                    n*=16;
                }else if(ch=='A'){
                    dec=10*n+dec;
                    n*=16;
                }else if(ch=='B'){
                    dec=11*n+dec;
                    n*=16;
                }else if(ch=='C'){
                    dec=12*n+dec;
                    n*=16;
                }else if(ch=='D'){
                    dec=13*n+dec;
                    n*=16;
                }else if(ch=='E'){
                    dec=14*n+dec;
                    n*=16;
                }else {
                    dec=15*n+dec;
                    n*=16;
                }
            }
            // alert(dec);
            return dec;
        }

        function setNum1(obj) {
            num1=""+obj.value;
        }

        function setNum2(obj) {
            num2=""+obj.value;
        }
        function convert() {

            var dec="";
            var inText=""+document.getElementById("inText").value;
            var result=document.getElementById("result");

            if(num1=="2"){
                dec=""+binaryToDec(inText);
            }else if (num1=="8"){
                dec=""+octToDec(inText);
            }else if(num1=="16"){
                dec=""+hexToDec(inText);
            }else {
                dec=""+inText;
            }

            if (num2=="2"){
                result.innerHTML=toBinary(dec);
            }else if (num2=="8"){
                result.innerHTML=toOct(dec);
            }else if(num2=="16"){
                result.innerHTML=toHex(dec);
            }else {
                result.innerHTML=dec;
            }

        }
    </script>

OK,整個專案講完了,是不是感覺人要沒了?可以去訪問我的GitHub原始碼,里面都有詳細的注釋,傳送門:
https://github.com/Nown1/calculator
在這里插入圖片描述

轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/251797.html

標籤:其他

上一篇:UILable addAttributes 根據html圖片內容進行高度設定

下一篇:前臺充值后臺沒有同步怎么回事

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • vue移動端上拉加載

    可能做得過于簡單或者比較low,請各位大佬留情,一起探討技術 ......

    uj5u.com 2020-09-10 04:38:07 more
  • 優美網站首頁,頂部多層導航

    一個個人用的瀏覽器首頁,可以把一下常用的網站放在這里,平常打開會比較方便。 第一步,HTML代碼 <script src=https://www.cnblogs.com/szharf/p/"js/jquery-3.4.1.min.js"></script> <div id="navigate"> <ul> <li class="labels labels_1"> ......

    uj5u.com 2020-09-10 04:38:47 more
  • 頁面為要加<!DOCTYPE html>

    最近因為寫一個js函式,需要用到$(window).height(); 由于手寫demo的時候,過于自信,其實對前端方面的認識也不夠體系,用文本檔案直接敲出來的html代碼,第一行沒有加上<!DOCTYPE html> 導致了$(window).height();的結果直接是整個document的高 ......

    uj5u.com 2020-09-10 04:38:52 more
  • WordPress網站程式手動升級要做好資料備份

    WordPress博客網站程式在進行升級前,必須要做好網站資料的備份,這個問題良家佐言是遇見過的;在剛開始接觸WordPress博客程式的時候,因為升級問題和博客網站的修改的一些嘗試,良家佐言是吃盡了苦頭。因為購買的是西部數碼的空間和域名,每當佐言把自己的WordPress博客網站搞到一塌糊涂的時候 ......

    uj5u.com 2020-09-10 04:39:30 more
  • WordPress程式不能升級為5.4.2版本的原因

    WordPress是一款個人博客系統,受到英文博客愛好者和中文博客愛好者的追捧,并逐步演化成一款內容管理系統軟體;它是使用PHP語言和MySQL資料庫開發的,用戶可以在支持PHP和MySQL資料庫的服務器上使用自己的博客。每一次WordPress程式的更新,就會牽動無數WordPress愛好者的心, ......

    uj5u.com 2020-09-10 04:39:49 more
  • 使用CSS3的偽元素進行首字母下沉和首行改變樣式

    網頁中常見的一種效果,首字改變樣式或者首行改變樣式,效果如下圖。 代碼: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, ......

    uj5u.com 2020-09-10 04:40:09 more
  • 關于a標簽的講解

    什么是a標簽? <a> 標簽定義超鏈接,用于從一個頁面鏈接到另一個頁面。 <a> 元素最重要的屬性是 href 屬性,它指定鏈接的目標。 a標簽的語法格式:<a href=https://www.cnblogs.com/summerxbc/p/"指定要跳轉的目標界面的鏈接">需要展示給用戶看見的內容</a> a標簽 在所有瀏覽器中,鏈接的默認外觀如下: 未被訪問的鏈接帶 ......

    uj5u.com 2020-09-10 04:40:11 more
  • 前端輪播圖

    在需要輪播的頁面是引入swiper.min.js和swiper.min.css swiper.min.js地址: 鏈接:https://pan.baidu.com/s/15Uh516YHa4CV3X-RyjEIWw 提取碼:4aks swiper.min.css地址 鏈接:https://pan.b ......

    uj5u.com 2020-09-10 04:40:13 more
  • 如何設定html中的背景圖片(全屏顯示,且不拉伸)

    1 <style>2 body{background-image:url(https://uploadbeta.com/api/pictures/random/?key=BingEverydayWallpaperPicture); 3 background-size:cover;background ......

    uj5u.com 2020-09-10 04:40:16 more
  • Java學習——HTML詳解(上)

    HTML詳解 初識HTML Hyper Text Markup Language(超文本標記語言) 1 <!--DOCTYPE:告訴瀏覽器我們要使用什么規范--> 2 <!DOCTYPE html> 3 <html lang="en"> 4 <head> 5 <!--meta 描述性的標簽,描述一些 ......

    uj5u.com 2020-09-10 04:40:33 more
最新发布
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 07:59:23 more
  • 生產事故-走近科學之消失的JWT

    入職多年,面對生產環境,盡管都是小心翼翼,慎之又慎,還是難免捅出簍子。輕則滿頭大汗,面紅耳赤。重則系統停擺,損失資金。每一個生產事故的背后,都是寶貴的經驗和教訓,都是專案成員的血淚史。為了更好地防范和遏制今后的各類事故,特開此專題,長期更新和記錄大大小小的各類事故。有些是親身經歷,有些是經人耳傳口授 ......

    uj5u.com 2023-04-18 07:55:04 more
  • 記錄--Canvas實作打飛字游戲

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 打開游戲界面,看到一個畫面簡潔、卻又富有挑戰性的游戲。螢屏上,有一個白色的矩形框,里面不斷下落著各種單詞,而我需要迅速地輸入這些單詞。如果我輸入的單詞與螢屏上的單詞匹配,那么我就可以獲得得分;如果我輸入的單詞錯誤或者時間過長,那么我就會輸 ......

    uj5u.com 2023-04-04 08:35:30 more
  • 了解 HTTP 看這一篇就夠

    在學習網路之前,了解它的歷史能夠幫助我們明白為何它會發展為如今這個樣子,引發探究網路的興趣。下面的這張圖片就展示了“互聯網”誕生至今的發展歷程。 ......

    uj5u.com 2023-03-16 11:00:15 more
  • 藍牙-低功耗中心設備

    //11.開啟藍牙配接器 openBluetoothAdapter //21.開始搜索藍牙設備 startBluetoothDevicesDiscovery //31.開啟監聽搜索藍牙設備 onBluetoothDeviceFound //30.停止監聽搜索藍牙設備 offBluetoothDevi ......

    uj5u.com 2023-03-15 09:06:45 more
  • canvas畫板(滑鼠和觸摸)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>canves</title> <style> #canvas { cursor:url(../images/pen.png),crosshair; } #canvasdiv{ bo ......

    uj5u.com 2023-02-15 08:56:31 more
  • 手機端H5 實作自定義拍照界面

    手機端 H5 實作自定義拍照界面也可以使用 MediaDevices API 和 <video> 標簽來實作,和在桌面端做法基本一致。 首先,使用 MediaDevices.getUserMedia() 方法獲取攝像頭媒體流,并將其傳遞給 <video> 標簽進行渲染。 接著,使用 HTML 的 < ......

    uj5u.com 2023-01-12 07:58:22 more
  • 記錄--短視頻滑動播放在 H5 下的實作

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 短視頻已經無數不在了,但是主體還是使用 app 來承載的。本文講述 H5 如何實作 app 的視頻滑動體驗。 無聲勝有聲,一圖頂百辯,且看下圖: 網址鏈接(需在微信或者手Q中瀏覽) 從上圖可以看到,我們主要實作的功能也是本文要講解的有: ......

    uj5u.com 2023-01-04 07:29:05 more
  • 一文讀懂 HTTP/1 HTTP/2 HTTP/3

    從 1989 年萬維網(www)誕生,HTTP(HyperText Transfer Protocol)經歷了眾多版本迭代,WebSocket 也在期間萌芽。1991 年 HTTP0.9 被發明。1996 年出現了 HTTP1.0。2015 年 HTTP2 正式發布。2020 年 HTTP3 或能正... ......

    uj5u.com 2022-12-24 06:56:02 more
  • 【HTML基礎篇002】HTML之form表單超詳解

    ??一、form表單是什么

    ??二、form表單的屬性

    ??三、input中的各種Type屬性值

    ??四、標簽 ......

    uj5u.com 2022-12-18 07:17:06 more