您现在的位置是:首页 > 技术教程 正文

微信小程序计算器(含源码)、含js精确运算代码

admin 阅读: 2024-03-30
后台-插件-广告管理-内容页头部广告(手机)

目录

一、引言与效果图

 二、源码

0.目录结构:

1.xxxx.wxml文件

 2.样式文件

(1)xxxx.less文件

(2)xxxx.wxss文件 (不会使用 less 的可以用这个)

3.xxxx.json文件

4.accurate.js

5.xxxx.js文件

三、结语


一、引言与效果图

       最近在做一个记账本小程序,其中需要用到计算器,但是在网上找的代码,用起来不是不符合我的想法,就是看着非常难受,于是还是自己写了一个

 二、源码

0.目录结构:

名字 ( test ) 是我随便取的,你们可以取别的,但是accurate.js的名字请勿改动

1.xxxx.wxml文件

对应上方目录结构的 : test.wxml

  1. <view class="counter">
  2. <view class="result">
  3. <view class="showResult">
  4. <view class="result-num">{{counter.posture[0]}}view>
  5. <view class="result-num">{{counter.posture[1]}}view>
  6. <view class="result-num">{{counter.posture[2]}}view>
  7. view>
  8. view>
  9. <view class="btns">
  10. <view class="row">
  11. <view class="col clear" hover-class="hover-bg" bindtap="resetBtn">Cview>
  12. <view class="col" hover-class="hover-bg" bindtap="delBtn">DELview>
  13. <view class="col chu" hover-class="hover-bg" bindtap="opBtn" data-val="%">%view>
  14. <view class="col" hover-class="hover-bg" bindtap="opBtn" data-val="÷">÷view>
  15. view>
  16. <view class="row">
  17. <view class="col" hover-class="hover-bg" bindtap="numBtn" data-val="7">7view>
  18. <view class="col" hover-class="hover-bg" bindtap="numBtn" data-val="8">8view>
  19. <view class="col" hover-class="hover-bg" bindtap="numBtn" data-val="9">9view>
  20. <view class="col" hover-class="hover-bg" bindtap="opBtn" data-val="×">×view>
  21. view>
  22. <view class="row">
  23. <view class="col" hover-class="hover-bg" bindtap="numBtn" data-val="4">4view>
  24. <view class="col" hover-class="hover-bg" bindtap="numBtn" data-val="5">5view>
  25. <view class="col" hover-class="hover-bg" bindtap="numBtn" data-val="6">6view>
  26. <view class="col" hover-class="hover-bg" bindtap="opBtn" data-val="-">-view>
  27. view>
  28. <view class="row">
  29. <view class="col" hover-class="hover-bg" bindtap="numBtn" data-val="1">1view>
  30. <view class="col" hover-class="hover-bg" bindtap="numBtn" data-val="2">2view>
  31. <view class="col" hover-class="hover-bg" bindtap="numBtn" data-val="3">3view>
  32. <view class="col" hover-class="hover-bg" bindtap="opBtn" data-val="+">+view>
  33. view>
  34. <view class="row">
  35. <view class="col zero" hover-class="hover-bg" bindtap="numBtn" data-val="0">0view>
  36. <view class="col" hover-class="hover-bg" bindtap="numBtn" data-val=".">.view>
  37. <view class="col save" hover-class="hover-bg" bindtap="finish">=view>
  38. view>
  39. view>
  40. view>

 2.样式文件

我是用less写的,所以这里先放less文件(不知道less怎么使用的,可以往下滑,看到wxss文件

对应上方目录结构的 : test.wxss 和 test.less

(1)xxxx.less文件

  1. page {
  2. display: flex;
  3. flex-direction: column;
  4. height: 100%;
  5. background-image: linear-gradient(to top, #a8edea 0%, #fed6e3 100%);
  6. }
  7. .counter {
  8. height: 100%;
  9. display: flex;
  10. flex-direction: column;
  11. font-size: 60rpx;
  12. border-top: 1rpx solid #ccc;
  13. border-left: 1rpx solid #ccc;
  14. .result {
  15. flex: 1;
  16. position: relative;
  17. width: 100%;
  18. box-sizing: border-box;
  19. display: flex;
  20. align-items: flex-end;
  21. justify-content: flex-end;
  22. border-bottom: 5rpx solid #d5dde1;
  23. background: rgba(215, 250, 252, 0.253);
  24. .showResult {
  25. display: flex;
  26. align-items: flex-end;
  27. justify-content: flex-end;
  28. flex-wrap: wrap;
  29. font-size: 100rpx;
  30. width: 100%;
  31. box-sizing: border-box;
  32. padding: 20rpx;
  33. .result-num {
  34. overflow-x: auto;
  35. text-align: end;
  36. word-wrap: break-word;
  37. }
  38. }
  39. }
  40. .btns {
  41. flex: 1;
  42. .row {
  43. display: flex;
  44. .col {
  45. flex-basis: 25%;
  46. height: 150rpx;
  47. border-right: 1rpx solid #ccc;
  48. border-bottom: 1rpx solid #ccc;
  49. box-sizing: border-box;
  50. display: flex;
  51. align-items: center;
  52. justify-content: center;
  53. font-size: 50rpx;
  54. &.clear {
  55. color: #f00;
  56. }
  57. &.zero {
  58. flex-basis: 50%;
  59. }
  60. &:last-child,
  61. &.chu {
  62. color: #008bfc;
  63. }
  64. &.save {
  65. color: #f90808;
  66. font-size: 80rpx;
  67. font-weight: 900;
  68. }
  69. &.hover-bg {
  70. background: rgba(255, 255, 255, 0.2);
  71. }
  72. }
  73. }
  74. }
  75. }

(2)xxxx.wxss文件 (不会使用 less 的可以用这个)

  1. page {
  2. display: flex;
  3. flex-direction: column;
  4. height: 100%;
  5. background-image: linear-gradient(to top, #a8edea 0%, #fed6e3 100%);
  6. }
  7. .counter {
  8. height: 100%;
  9. display: flex;
  10. flex-direction: column;
  11. font-size: 60rpx;
  12. border-top: 1rpx solid #ccc;
  13. border-left: 1rpx solid #ccc;
  14. }
  15. .counter .result {
  16. flex: 1;
  17. position: relative;
  18. width: 100%;
  19. box-sizing: border-box;
  20. display: flex;
  21. align-items: flex-end;
  22. justify-content: flex-end;
  23. border-bottom: 5rpx solid #d5dde1;
  24. background: rgba(215, 250, 252, 0.253);
  25. }
  26. .counter .result .showResult {
  27. display: flex;
  28. align-items: flex-end;
  29. justify-content: flex-end;
  30. flex-wrap: wrap;
  31. font-size: 100rpx;
  32. width: 100%;
  33. box-sizing: border-box;
  34. padding: 20rpx;
  35. }
  36. .counter .result .showResult .result-num {
  37. overflow-x: auto;
  38. text-align: end;
  39. word-wrap: break-word;
  40. }
  41. .counter .btns {
  42. flex: 1;
  43. }
  44. .counter .btns .row {
  45. display: flex;
  46. }
  47. .counter .btns .row .col {
  48. transition: all 0.3s;
  49. flex-basis: 25%;
  50. height: 150rpx;
  51. border-right: 1rpx solid #ccc;
  52. border-bottom: 1rpx solid #ccc;
  53. box-sizing: border-box;
  54. display: flex;
  55. align-items: center;
  56. justify-content: center;
  57. font-size: 50rpx;
  58. }
  59. .counter .btns .row .col.clear {
  60. color: #f00;
  61. }
  62. .counter .btns .row .col.zero {
  63. flex-basis: 50%;
  64. }
  65. .counter .btns .row .col:last-child,
  66. .counter .btns .row .col.chu {
  67. color: #008bfc;
  68. }
  69. .counter .btns .row .col.save {
  70. color: #f90808;
  71. font-size: 80rpx;
  72. font-weight: 900;
  73. }
  74. .counter .btns .row .col.hover-bg {
  75. background: rgba(255, 255, 255, 0.2);
  76. }

3.xxxx.json文件

对应上方目录结构的 : test.json

  1. {
  2. "usingComponents": {},
  3. "navigationBarTitleText": "计算器",
  4. "navigationBarBackgroundColor": "#f4dfe9"
  5. }

4.accurate.js

对应上方目录结构的 : accurate.js ,请勿改名

这个文件是用于进行精确计算的:因为js自带的浮点数计算有bug!用这个函数进行加减乘除,可以防止浮点数运算出现问题

  1. module.exports = {
  2. //加法 add
  3. add(arg1, arg2) {
  4. let r1, r2, m;
  5. try {
  6. r1 = arg1.toString().split(".")[1].length;
  7. } catch (e) {
  8. r1 = 0;
  9. }
  10. try {
  11. r2 = arg2.toString().split(".")[1].length;
  12. } catch (e) {
  13. r2 = 0;
  14. }
  15. m = Math.pow(10, Math.max(r1, r2));
  16. return (arg1 * m + arg2 * m) / m;
  17. },
  18. //减法 subtraction
  19. sub(arg1, arg2) {
  20. let r1, r2, m, n;
  21. try {
  22. r1 = arg1.toString().split(".")[1].length;//获取小数点后的长度
  23. } catch (e) {
  24. r1 = 0;
  25. }
  26. try {
  27. r2 = arg2.toString().split(".")[1].length;//获取小数点后的长度
  28. } catch (e) {
  29. r2 = 0;
  30. }
  31. m = Math.pow(10, Math.max(r1, r2));
  32. n = (r1 >= r2) ? r1 : r2;
  33. return ((arg1 * m - arg2 * m) / m).toFixed(n);
  34. },
  35. //乘法 multiplication
  36. mul(arg1, arg2) {
  37. let m = 0,
  38. s1 = arg1.toString(),
  39. s2 = arg2.toString();
  40. try {
  41. m += s1.split(".")[1].length;
  42. } catch (e) {}
  43. try {
  44. m += s2.split(".")[1].length;
  45. } catch (e) {}
  46. return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
  47. },
  48. //除法 division
  49. div(arg1, arg2) {
  50. let t1 = 0,
  51. t2 = 0,
  52. r1, r2;
  53. try {
  54. t1 = arg1.toString().split(".")[1].length;
  55. } catch (e) {}
  56. try {
  57. t2 = arg2.toString().split(".")[1].length;
  58. } catch (e) {}
  59. r1 = Number(arg1.toString().replace(".", ""));
  60. r2 = Number(arg2.toString().replace(".", ""));
  61. return (r1 / r2) * Math.pow(10, t2 - t1);
  62. }
  63. }

5.xxxx.js文件

对应上方目录结构的 test.js

我的做法是,使用一个长度为3的数组,存储式子的 “左” “中” “右” 的数字或操作符,然后再进行一些特殊情况的处理

  1. //引入精确计算的js
  2. const acc = require('./accurate.js');
  3. Page({
  4. data: {
  5. counter: {
  6. posture: ['', '', ''], //存放式子,比如 1 + 12
  7. ansType: false, //判断是否是手动点击的等于号
  8. },
  9. },
  10. //输入数字
  11. numBtn(e) {
  12. let num = e.currentTarget.dataset.val
  13. let posture = this.data.counter.posture
  14. if (posture[1] === '') { //如果运算符为空,就在式子数组第0个位置放入内容
  15. //判断特殊情况1: 小数点
  16. if (num == '.' && posture[0] == '') { //如果是点,且字符串为空,就默认加上 0
  17. posture[0] = '0'
  18. } else if (num == '.' && posture[0].indexOf('.') > -1) { //如果已经有点了还按
  19. console.log('已经有点,不能再按');
  20. return
  21. }
  22. //判断特殊情况2:如果是手动点了等号之后,再按数字,不应该在原位置加,而是清空再加 (通过其它方式比如 “1+2+“ 调用的finish函数不算,需要是手动点击的,判断方法:手动点击的等号有事件对象e)
  23. if (this.data.counter.ansType) {
  24. posture[0] = ''
  25. this.setData({
  26. 'counter.ansType': false //生效一次即可取消
  27. })
  28. }
  29. //判断特殊情况3:如果这里面只有0,那么就删掉这个0,再增加(想输入小数点除外)
  30. if (num !== '.' &&posture[0] == '0') {
  31. posture[0] = ''
  32. }
  33. this.setData({
  34. 'counter.posture[0]': posture[0] + num
  35. })
  36. } else { //如果运算符不为空,就在式子数组第2个位置放入内容
  37. //判断特殊情况: 小数点
  38. if (num == '.' && posture[2] == '') { //如果是点,且字符串为空,就默认加上 0
  39. posture[2] = '0'
  40. } else if (num == '.' && posture[2].indexOf('.') > -1) { //如果已经有点了还按
  41. console.log('已经有点,不能再按');
  42. return
  43. }
  44. //判断特殊情况2:如果这里面只有0,那么就删掉这个0,再增加 (想输入小数点除外)
  45. if (num !== '.' && posture[2] == '0') {
  46. posture[2] = ''
  47. }
  48. this.setData({
  49. 'counter.posture[2]': posture[2] + num
  50. })
  51. }
  52. console.log(this.data.counter.posture);
  53. },
  54. //输入运算符
  55. opBtn(e) {
  56. let op = e.currentTarget.dataset.val
  57. let posture = this.data.counter.posture
  58. if (posture[2] == '') { //如果式子最后一位为空的话,就把符号放进去运算符位置
  59. this.setData({
  60. 'counter.posture[1]': op
  61. })
  62. } else { //否则就先运算,再放进去
  63. this.finish()
  64. this.setData({
  65. 'counter.posture[1]': op
  66. })
  67. }
  68. console.log(this.data.counter.posture);
  69. },
  70. //运算
  71. finish(e) {
  72. let posture = this.data.counter.posture
  73. let left = parseFloat(posture[0] || 0) //左数字 如果是空字符串就设置为0
  74. let right = parseFloat(posture[2] || 0) //右数字 如果是空字符串就设置为0
  75. let ans = 0 //答案
  76. console.log(left, right);
  77. switch (posture[1]) { //根据不同运算符,进行不同的运算
  78. case '+':
  79. ans = acc.add(left, right)
  80. break;
  81. case '-':
  82. ans = acc.sub(left, right)
  83. break;
  84. case '×':
  85. ans = acc.mul(left, right)
  86. break;
  87. case '÷':
  88. if (right == 0) { //如果数字不合规
  89. wx.showToast({
  90. title: '不能除 0 哦',
  91. icon: 'none'
  92. })
  93. ans = left
  94. } else {
  95. let _ans = acc.div(left, right)
  96. let x = String(_ans).indexOf('.') + 1;
  97. let y = String(_ans).length - x;
  98. if (y > 10) {
  99. ans = _ans.toFixed(10);
  100. } else {
  101. ans = _ans
  102. }
  103. }
  104. break;
  105. case '%':
  106. if (right == 0) { //如果数字不合规
  107. wx.showToast({
  108. title: '不能余 0 哦',
  109. icon: 'none'
  110. })
  111. ans = left
  112. } else {
  113. ans = left % right
  114. }
  115. break;
  116. default:
  117. ans = left
  118. break;
  119. }
  120. console.log(ans);
  121. posture = ['' + ans, '', ''] //清空数组,把答案放在第一位
  122. let ansType = false
  123. if (e) { //如果有事件对象,说明是手动点击的”=“,应该加一个标识符,点了=再点数字的时候,应该把左边数字清空再处理数字
  124. console.log('手动点击的等于号,后面点击数字时,将清空左边数字');
  125. ansType = true
  126. }
  127. this.setData({
  128. 'counter.posture': posture,
  129. 'counter.ansType': ansType
  130. })
  131. },
  132. //清空
  133. resetBtn() {
  134. this.setData({
  135. 'counter.posture': ['', '', ''],
  136. })
  137. },
  138. //退位
  139. delBtn() {
  140. let posture = this.data.counter.posture
  141. //从右到左的顺序删除
  142. if (posture[2]) { //如果最后一位不为空,就先删它
  143. posture[2] = posture[2].substr(0, posture[2].length - 1)
  144. } else if (posture[1]) { //如果符号位不为空,就删它
  145. posture[1] = ''
  146. } else if (posture[0]) { //如果第一位不为空,就删它
  147. posture[0] = posture[0].substr(0, posture[0].length - 1)
  148. } else return //否则就不做事
  149. this.setData({
  150. 'counter.posture': posture
  151. })
  152. console.log(this.data.counter.posture);
  153. },
  154. })

三、结语

这次的小程序源码分享到此结束,如果遇到了源码中出现了什么bug,欢迎在评论区指出

如果你有更好的实现方式,希望大家不吝赐教

经过评论区提醒,已对除法结果小数点后长度进行限制,同时修改了部分样式表,使得数字超长时会自动换行

标签:
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

在线投稿:投稿 站长QQ:1888636

后台-插件-广告管理-内容页尾部广告(手机)
关注我们

扫一扫关注我们,了解最新精彩内容

搜索