简易的JS计算器实现代码


Posted in Javascript onOctober 18, 2016

看看手机中的计算器,分为普通计算器和科学计算器

简易的JS计算器实现代码

 自认脑袋不够大,就实现一个普通版本的吧(支持正负数加减乘除等基本连续的运算,未提供括号功能)

看看图示效果:

简易的JS计算器实现代码

一、知识准备

1+1 = ?

正常来说,我们看到这个表达式都知道怎么运算,知道运算结果

但计算机不一样,计算机无法识别出这串表达式,它只能识别特定的规则:前缀表达式+ 1 1 或后缀表达式1 1 +

举个栗子

(3 + 4) × 5 - 6 就是中缀表达式
- × + 3 4 5 6 前缀表达式
3 4 + 5 × 6 - 后缀表达式 

所以为了实现程序的自动运算,我们需要将输入的数据转化为前缀或后缀表达式

前缀、中缀、后缀表达式的概念以及相互转换方法在这里就不多说了,这篇博文 说得比较清楚了

所以,在这个计算器的实现中,采用了后缀表达式的实现方式,参考以上文章,重点关注这两个算法:

与转换为前缀表达式相似,遵循以下步骤:
(1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2;
(2) 从左至右扫描中缀表达式;
(3) 遇到操作数时,将其压入S2;
(4) 遇到运算符时,比较其与S1栈顶运算符的优先级:
(4-1) 如果S1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;
(4-2) 否则,若优先级比栈顶运算符的高,也将运算符压入S1(注意转换为前缀表达式时是优先级较高或相同,而这里则不包括相同的情况);
(4-3) 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较;
(5) 遇到括号时:
(5-1) 如果是左括号“(”,则直接压入S1;
(5-2) 如果是右括号“)”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到左括号为止,此时将这一对括号丢弃;
(6) 重复步骤(2)至(5),直到表达式的最右边;
(7) 将S1中剩余的运算符依次弹出并压入S2;
(8) 依次弹出S2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式(转换为前缀表达式时不用逆序)。

与前缀表达式类似,只是顺序是从左至右:
从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素 op 栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果。
例如后缀表达式“3 4 + 5 × 6 -”:
(1) 从左至右扫描,将3和4压入堆栈;
(2) 遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素,注意与前缀表达式做比较),计算出3+4的值,得7,再将7入栈;
(3) 将5入栈;
(4) 接下来是×运算符,因此弹出5和7,计算出7×5=35,将35入栈;
(5) 将6入栈;
(6) 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。

二、实现过程

第一步当然是搭建计算器的页面结构,不是科学计算器,只提供了基本的运算功能,但也能即时地进行运算,显示出完整的中缀表达式,运算后保存上一条运算记录。

要先说一下:本来想实现小数点功能的,但小数点的存在让数据存储与数据显示的实现有了压力,实现过程实在脑大,索性先取消这个功能。 

1. 页面结构:

<h5>计算计算</h5>
  <!-- 计算器 -->
  <div class="calc-wrap">
    <div class="calc-in-out">
      <!-- 上一条运算记录 -->
      <p class="calc-history" title=""></p>
      <!-- 输入的数据 -->
      <p class="calc-in"></p>
      <!-- 输出的运算结果 -->
      <p class="calc-out active"></p>
    </div>
    <table class="calc-operation">
      <thead></thead>
      <tbody>
        <tr>
          <td data-ac="cls" class="cls">C</td>
          <td data-ac="del">←</td>
          <td data-ac="sq">x<sup>2</sup></td>
          <td data-ac="mul">×</td>
        </tr>
        <tr>
          <td data-val="7">7</td>
          <td data-val="8">8</td>
          <td data-val="9">9</td>
          <td data-ac="div">÷</td>
        </tr>
        <tr>
          <td data-val="4">4</td>
          <td data-val="5">5</td>
          <td data-val="6">6</td>
          <td data-ac="plus">+</td>
        </tr>
        <tr>
          <td data-val="1">1</td>
          <td data-val="2">2</td>
          <td data-val="3">3</td>
          <td data-ac="minus">-</td>
        </tr>
          <td data-ac="per">%</td>
          <td data-val="0">0</td>
          <td data-ac="dot">.</td>
          <td data-ac="eq" class="eq">=</td>
      </tbody>
    </table>
  </div>

2. 结合一点样式:

body {
  padding: 20px;
  font-family: Arial;
}

.calc-wrap {
  width: 300px;
  border: 1px solid #ddd;
  border-radius: 3px;
}


.calc-operation {
  width: 100%;
  border-collapse: collapse;
}

.calc-in-out {
  width: 100%;
  padding: 10px 20px;
  text-align: right;
  box-sizing: border-box;
  background-color: rgba(250, 250, 250, .9);
}
.calc-in-out p {
  overflow: hidden;
  margin: 5px;
  width: 100%;
}
.calc-history {
  margin-left: -20px;
  font-size: 18px;
  color: #bbb;
  border-bottom: 1px dotted #ddf;
  min-height: 23px;
}

.calc-in,
.calc-out {
  font-size: 20px;
  color: #888;
  line-height: 39px;
  min-height: 39px;
}

.calc-in {
  color: #888;
}
.calc-out {
  color: #ccc;
}

.calc-in.active,
.calc-out.active {
  font-size: 34px;
  color: #666;
}

.calc-operation td {
  padding: 10px;
  width: 25%;
  text-align: center;
  border: 1px solid #ddd;
  font-size: 26px;
  color: #888;
  cursor: pointer;
}

.calc-operation td:active {
  background-color: #ddd;
}

.calc-operation .cls {
  color: #ee8956;
}

这样静态的计算器就粗来了~~

 简易的JS计算器实现代码

3. JS逻辑

这部分就是重点了,一步步来说

首先是对计算器的监听吧,也就是这个表格,可以使用事件委托的方式,在父级节点上监听处理

// 绑定事件
    bindEvent: function() {
      var that = this;

      that.$operation.on('click', function(e) {
        e = e || window.event;
        var elem = e.target || e.srcElement,
          val,
          action;

        if (elem.tagName === 'TD') {
          val = elem.getAttribute('data-val') || elem.getAttribute('data-ac');

监听数据,获取到的只是页面上的某个值/操作符,所以需要将数据存储起来形成中缀,再由中缀转换成后缀,最后通过后缀进行计算

// 中缀表达式
    this.infix = [];
    // 后缀表达式
    this.suffix = [];
    // 后缀表达式运算结果集
    this.result = [];

按照算法步骤,实现出来,这里没有使用到括号,如果实际需要,可在相应位置修改判断条件即可~

// 中缀表达式转后缀
    infix2Suffix: function() {
      var temp = [];
      this.suffix = [];

      for (var i = 0; i < this.infix.length; i++) {
        // 数值,直接压入
        if (!this.isOp(this.infix[i])) {
          this.suffix.push(this.infix[i]);
        }
        else {
          if (!temp.length) {
            temp.push(this.infix[i]);
          }
          else {
            var opTop = temp[temp.length - 1];
            // 循环判断运算符优先级,将运算符较高的压入后缀表达式
            if (!this.priorHigher(opTop, this.infix[i])) {
              while (temp.length && !this.priorHigher(opTop, this.infix[i])) {
                this.suffix.push(temp.pop());
                opTop = temp[temp.length - 1];
              }
            }
              // 将当前运算符也压入后缀表达式
            temp.push(this.infix[i]);
          }
        }
      }
      // 将剩余运算符号压入
      while (temp.length) {
        this.suffix.push(temp.pop());
      }
    },
// 后缀表达式计算
    calcSuffix: function() {
      this.result = [];

      for (var i = 0; i < this.suffix.length; i++) {
        // 数值,直接压入结果集
        if (!this.isOp(this.suffix[i])) {
          this.result.push(this.suffix[i]);
        }
        // 运算符,从结果集中取出两项进行运算,并将运算结果置入结果集合
        else {
          this.result.push(this.opCalc(this.result.pop(), this.suffix[i], this.result.pop()));
        }
      }
      // 此时结果集中只有一个值,即为结果
       return this.result[0];
    }

其实,在实现的时候会发现,中缀、后缀只是一个难点,更复杂的地方是整个计算器的状态变化(或者说是数据变化)

在这个简单的计算器中,就有数字(0-9)、运算符(+ - * /)、操作(清除 删除)、预运算(百分号 平方)、小数点、即时运算等数据及操作

如果是科学计算器那就更复杂了,所以理清如何控制这些东西很关键,而其中最重要的就是中缀表达式的构建与存储

 当连续点击+号时,是不符合实际操作的,所以需要一个变量 lastVal 来记录上一个值,随着操作而更新,再通过判断,防止程序出错

在点击=号之后,我们可以继续使用这个结果进行运算,或者重新开始运算

// 构建中缀表达式
    buildInfix: function(val, type) {
      // 直接的点击等于运算之后,
      if (this.calcDone) {
        this.calcDone = false;
        // 再点击数字,则进行新的运算
        if (!this.isOp(val)) {
          this.resetData();
        }
        // 再点击运算符,则使用当前的结果值继续进行运算
        else {
          var re = this.result[0];
          this.resetData();
          this.infix.push(re);
        }

      }

      var newVal;
       ...

点击删除,是删除一位数,不是直接地删除一个数,然后更新中缀表达式的值

// 删除操作
      if (type === 'del') {
        newVal = this.infix.pop();
        // 删除末尾一位数
        newVal = Math.floor(newVal / 10);
        if (newVal) {
          this.infix.push(newVal);
        }

        this.lastVal = this.infix[this.infix.length - 1];
        return this.infix;
      }

而添加操作,要考虑的就更多了,比如连续的连续运算符、连续的数字、运算符+ - 接上数字表示正负数,小数点的连接存取等

// 添加操作,首先得判断运算符是否重复
      else if (type === 'add') {
        // 两个连续的运算符
        if (this.isOp(val) && this.isOp(this.lastVal)) {
          return this.infix;
        }
        // 两个连续的数字
        else if (!this.isOp(val) && !this.isOp(this.lastVal)) {
          newVal = this.lastVal * 10 + val;
          this.infix.pop();
          this.infix.push(this.lastVal = newVal);

          return this.infix;
        }
        // 首个数字正负数
        if (!this.isOp(val) && this.infix.length === 1 && (this.lastVal === '+' || this.lastVal === '-')) {
          newVal = this.lastVal === '+' ? val : 0 - val;
          this.infix.pop();
          this.infix.push(this.lastVal = newVal);

          return this.infix;
        }


        this.infix.push(this.lastVal = val);
        return this.infix;
      }

在很多次操作的时候,计算器都需要即时地进行运算,为简化代码,可以封装成一个方法,在相应的位置调用即可

// 即时得进行运算
    calculate: function(type) {
      this.infix2Suffix();
      var suffixRe = this.calcSuffix();

      if (suffixRe) {
        this.$out.text('=' + suffixRe)
          .attr('title', suffixRe)
          .removeClass('active');

        // 如果是直接显示地进行等于运算
        if (type === 'eq') {
          this.$in.removeClass('active');
          this.$out.addClass('active');
          // 设置标记:当前已经显示地进行计算
          this.calcDone = true;
          this.lastVal = suffixRe;
          // 设置历史记录
          var history = this.infix.join('') + ' = ' + suffixRe;
          this.$history.text(history).attr('title', history);
        }

      }
    },

剩下的就是点击之后的处理过程了,也就是各种调用处理 传递数据->构建中缀处理数据->中缀转后缀->后缀运算显示

比如点击了数字

// 数字:0-9
          if (!isNaN(parseInt(val, 10))) {
            // 构建中缀表达式并显示
            var infixRe = that.buildInfix(parseInt(val, 10), 'add');
            that.$in.text(infixRe.join('')).addClass('active');

            that.calculate();

            return;
          }

又比如几个预运算,其实长得也差不多

// 预运算:百分比、小数点、平方
          else if (['per', 'dot', 'sq'].indexOf(action) !== -1) {
            if (!that.infix.length || that.isOp(that.lastVal)) {
              return;
            }

            if (action === 'per') {
              that.lastVal /= 100;
            } else if (action === 'sq') {
              that.lastVal *= that.lastVal;
            } else if (action === 'dot') {
              // that.curDot = true;
            }

            // 重新构建中缀表达式
            var infixRe = that.buildInfix(that.lastVal, 'change');
            that.$in.text(infixRe.join('')).addClass('active');

            that.calculate();
          }

以上就是这个简单计算器的实现步骤了,变化太多还不敢保证不会出错

基本逻辑如此,如果要加上小数点运算、括号运算、正余弦等科学计算器的功能,还是自己去实现吧。。脑大啊。。 

$(function() {

  function Calculator($dom) {
    this.$dom = $($dom);
    // 历史运算
    this.$history = this.$dom.find('.calc-history');
    // 输入区
    this.$in = this.$dom.find('.calc-in');
    // 输出区
    this.$out = this.$dom.find('.calc-out');
    this.$operation = this.$dom.find('.calc-operation');

    // 运算符映射
    this.op = {
      'plus': '+',
      'minus': '-',
      'mul': '*',
      'div': '/'
    };
    this.opArr = ['+', '-', '*', '/'];

    // 中缀表达式
    this.infix = [];
    // 后缀表达式
    this.suffix = [];
    // 后缀表达式运算结果集
    this.result = [];
    // 存储最近的值
    this.lastVal = 0;
    // 当前已经计算等于完成
    this.calcDone = false;
    // 当前正在进行小数点点(.)相关值的修正
    this.curDot = false;

    this.init();
  }

  Calculator.prototype = {
    constructor: Calculator,
    // 初始化
    init: function() {
      this.bindEvent();
    },
    // 绑定事件
    bindEvent: function() {
      var that = this;

      that.$operation.on('click', function(e) {
        e = e || window.event;
        var elem = e.target || e.srcElement,
          val,
          action;

        if (elem.tagName === 'TD') {
          val = elem.getAttribute('data-val') || elem.getAttribute('data-ac');
          // 数字:0-9
          if (!isNaN(parseInt(val, 10))) {
            // 构建中缀表达式并显示
            var infixRe = that.buildInfix(parseInt(val, 10), 'add');
            that.$in.text(infixRe.join('')).addClass('active');

            that.calculate();

            return;
          }

          action = val;

          // 操作:清除、删除、计算等于
          if (['cls', 'del', 'eq'].indexOf(action) !== -1) {
            if (!that.infix.length) {
              return;
            }

            // 清空数据
            if (action === 'cls' || (action === 'del' && that.calcDone)) {
              that.$in.text('');
              that.$out.text('');

              that.resetData();
            }
            // 清除
            else if (action === 'del') {
              // 重新构建中缀表达式
              var infixRe = that.buildInfix(that.op[action], 'del');
              that.$in.text(infixRe.join('')).addClass('active');

              that.calculate();

            }
            // 等于
            else if (action === 'eq') {
              that.calculate('eq');

            }
          }
          // 预运算:百分比、小数点、平方
          else if (['per', 'dot', 'sq'].indexOf(action) !== -1) {
            if (!that.infix.length || that.isOp(that.lastVal)) {
              return;
            }

            if (action === 'per') {
              that.lastVal /= 100;
            } else if (action === 'sq') {
              that.lastVal *= that.lastVal;
            } else if (action === 'dot') {
              // that.curDot = true;
            }

            // 重新构建中缀表达式
            var infixRe = that.buildInfix(that.lastVal, 'change');
            that.$in.text(infixRe.join('')).addClass('active');

            that.calculate();
          }
          // 运算符:+ - * /
          else if (that.isOp(that.op[action])) {
            if (!that.infix.length && (that.op[action] === '*' || that.op[action] === '/')) {
              return;
            }

            var infixRe = that.buildInfix(that.op[action], 'add');
            that.$in.text(infixRe.join('')).addClass('active');
          }
        }
      });
    },

    resetData: function() {
      this.infix = [];
      this.suffix = [];
      this.result = [];
      this.lastVal = 0;
      this.curDot = false;
    },

    // 构建中缀表达式
    buildInfix: function(val, type) {
      // 直接的点击等于运算之后,
      if (this.calcDone) {
        this.calcDone = false;
        // 再点击数字,则进行新的运算
        if (!this.isOp(val)) {
          this.resetData();
        }
        // 再点击运算符,则使用当前的结果值继续进行运算
        else {
          var re = this.result[0];
          this.resetData();
          this.infix.push(re);
        }

      }

      var newVal;

      // 删除操作
      if (type === 'del') {
        newVal = this.infix.pop();
        // 删除末尾一位数
        newVal = Math.floor(newVal / 10);
        if (newVal) {
          this.infix.push(newVal);
        }

        this.lastVal = this.infix[this.infix.length - 1];
        return this.infix;
      }
      // 添加操作,首先得判断运算符是否重复
      else if (type === 'add') {
        // 两个连续的运算符
        if (this.isOp(val) && this.isOp(this.lastVal)) {
          return this.infix;
        }
        // 两个连续的数字
        else if (!this.isOp(val) && !this.isOp(this.lastVal)) {
          newVal = this.lastVal * 10 + val;
          this.infix.pop();
          this.infix.push(this.lastVal = newVal);

          return this.infix;
        }
        // 首个数字正负数
        if (!this.isOp(val) && this.infix.length === 1 && (this.lastVal === '+' || this.lastVal === '-')) {
          newVal = this.lastVal === '+' ? val : 0 - val;
          this.infix.pop();
          this.infix.push(this.lastVal = newVal);

          return this.infix;
        }

      // TODO: 小数点运算
      //   if (this.isOp(val)) {
      //     this.curDot = false;
      //   }

      //   // 小数点
      //   if (this.curDot) {
      //     var dotLen = 0;
      //     newVal = this.infix.pop();
      //     dotLen = newVal.toString().split('.');
      //     dotLen = dotLen[1] ? dotLen[1].length : 0;

      //     newVal += val / Math.pow(10, dotLen + 1);
      //     // 修正小数点运算精确值
      //     newVal = parseFloat(newVal.toFixed(dotLen + 1));

      //     this.infix.push(this.lastVal = newVal);
      //     return this.infix;
      //   }

        this.infix.push(this.lastVal = val);
        return this.infix;
      }

      // 更改操作,比如%的预运算
      else if (type === 'change') {
        this.infix.pop();
        this.infix.push(this.lastVal = val);

        return this.infix;
      }

    },
    // 判断是否为运算符
    isOp: function(op) {
      return op && this.opArr.indexOf(op) !== -1;
    },
    // 判断运算符优先级
    priorHigher: function(a, b) {
      return (a === '+' || a === '-') && (b === '*' || b === '/');
    },
    // 进行运算符的运算
    opCalc: function(b, op, a) {
      return op === '+'
        ? a + b
        : op === '-'
        ? a - b
        : op === '*'
        ? a * b
        : op === '/'
        ? a / b
        : 0;
    },
    // 即时得进行运算
    calculate: function(type) {
      this.infix2Suffix();
      var suffixRe = this.calcSuffix();

      if (suffixRe) {
        this.$out.text('=' + suffixRe)
          .attr('title', suffixRe)
          .removeClass('active');

        // 如果是直接显示地进行等于运算
        if (type === 'eq') {
          this.$in.removeClass('active');
          this.$out.addClass('active');
          // 设置标记:当前已经显示地进行计算
          this.calcDone = true;
          this.lastVal = suffixRe;
          // 设置历史记录
          var history = this.infix.join('') + ' = ' + suffixRe;
          this.$history.text(history).attr('title', history);
        }

      }
    },

    // 中缀表达式转后缀
    infix2Suffix: function() {
      var temp = [];
      this.suffix = [];

      for (var i = 0; i < this.infix.length; i++) {
        // 数值,直接压入
        if (!this.isOp(this.infix[i])) {
          this.suffix.push(this.infix[i]);
        }
        else {
          if (!temp.length) {
            temp.push(this.infix[i]);
          }
          else {
            var opTop = temp[temp.length - 1];
            // 循环判断运算符优先级,将运算符较高的压入后缀表达式
            if (!this.priorHigher(opTop, this.infix[i])) {
              while (temp.length && !this.priorHigher(opTop, this.infix[i])) {
                this.suffix.push(temp.pop());
                opTop = temp[temp.length - 1];
              }
            }
              // 将当前运算符也压入后缀表达式
            temp.push(this.infix[i]);
          }
        }
      }
      // 将剩余运算符号压入
      while (temp.length) {
        this.suffix.push(temp.pop());
      }
    },

    // 后缀表达式计算
    calcSuffix: function() {
      this.result = [];

      for (var i = 0; i < this.suffix.length; i++) {
        // 数值,直接压入结果集
        if (!this.isOp(this.suffix[i])) {
          this.result.push(this.suffix[i]);
        }
        // 运算符,从结果集中取出两项进行运算,并将运算结果置入结果集合
        else {
          this.result.push(this.opCalc(this.result.pop(), this.suffix[i], this.result.pop()));
        }
      }
      // 此时结果集中只有一个值,即为结果
       return this.result[0];
    }
  };

  new Calculator('.calc-wrap');
});

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript 折半查找字符在数组中的位置(有序列表)
Dec 09 Javascript
web前端开发也需要日志
Dec 09 Javascript
使用按钮控制以何种方式打开新窗口的属性介绍
Dec 17 Javascript
jQuery之折叠面板的深入解析
Jun 19 Javascript
js实现目录链接,内容跟着目录滚动显示的简单实例
Oct 15 Javascript
详解angular中如何监控dom渲染完毕
Jan 03 Javascript
JS实现加载和读取XML文件的方法详解
Apr 24 Javascript
原生JS实现层叠轮播图
May 17 Javascript
mpvue微信小程序多列选择器用法之省份城市选择的实现
Mar 07 Javascript
javascript实现蒙版与禁止页面滚动
Jan 11 Javascript
Node.js API详解之 assert模块用法实例分析
May 26 Javascript
jQuery实现容器间的元素拖拽功能
Dec 01 jQuery
用自定义图片代替原生checkbox实现全选,删除以及提交的方法
Oct 18 #Javascript
jquery中用jsonp实现搜索框功能
Oct 18 #Javascript
JavaScript排序算法动画演示效果的实现方法
Oct 18 #Javascript
浅谈js的异步执行
Oct 18 #Javascript
Jquery AJAX POST与GET之间的区别详细介绍
Oct 17 #Javascript
微信小程序 教程之模块化
Oct 17 #Javascript
微信小程序 教程之注册页面
Oct 17 #Javascript
You might like
PHP基础学习小结
2011/04/17 PHP
解析左右值无限分类的实现算法
2013/06/20 PHP
微信公众平台消息接口校验与消息接口响应实例
2014/12/23 PHP
JavaScript 数组循环引起的思考
2010/01/01 Javascript
Array.prototype 的泛型应用分析
2010/04/30 Javascript
Javascript实现飞动广告效果的方法
2015/05/25 Javascript
JavaScript中的getTime()方法使用详解
2015/06/10 Javascript
js控制元素显示在屏幕固定位置及监听屏幕高度变化的方法
2015/08/11 Javascript
javascript实现简单的全选和反选功能
2016/01/05 Javascript
JS实现CheckBox复选框全选、不选或全不选功能
2020/07/28 Javascript
jquery+Jscex打造游戏力度条
2020/09/12 Javascript
node.js 和HTML5开发本地桌面应用程序
2016/12/13 Javascript
原生JS实现《别踩白块》游戏(兼容IE)
2017/02/20 Javascript
nodejs中解决异步嵌套循环和循环嵌套异步的问题
2017/07/12 NodeJs
JS中Swiper的使用和轮播图效果
2017/08/11 Javascript
javascript将非数值转换为数值
2018/09/13 Javascript
js的新生代垃圾回收知识点总结
2019/08/22 Javascript
js实现简单的随机点名器
2020/09/17 Javascript
[55:02]2014 DOTA2国际邀请赛中国区预选赛 HGT VS Orenda
2014/05/21 DOTA
[02:02]特效爆炸!DOTA2珍宝之瓶待你开启
2018/08/21 DOTA
Python中exit、return、sys.exit()等使用实例和区别
2015/05/28 Python
python通过robert、sobel、Laplace算子实现图像边缘提取详解
2019/08/21 Python
python动态视频下载器的实现方法
2019/09/16 Python
python 消除 futureWarning问题的解决
2019/12/25 Python
Python Numpy,mask图像的生成详解
2020/02/19 Python
CSS3弹性盒模型开发笔记(三)
2016/04/26 HTML / CSS
是否可以从一个static方法内部发出对非static方法的调用?
2014/08/18 面试题
法院实习人员自我鉴定
2013/09/26 职场文书
化学教师自荐信范文
2013/12/28 职场文书
舞蹈比赛获奖感言
2014/02/04 职场文书
军训考核自我鉴定
2014/02/13 职场文书
小学生学习感言
2014/03/10 职场文书
专题组织生活会发言材料
2014/10/17 职场文书
党员群众路线整改措施及今后努力方向
2014/10/28 职场文书
MySQL 十大常用字符串函数详解
2021/06/30 MySQL
Spring IOC容器Bean的作用域及生命周期实例
2022/05/30 Java/Android