Gorsonpy的计算器

news2024/12/26 15:28:14

Gorsonpy的计算器

      • 0.页面及功能展示
      • 1. PSP表格
      • 2.解题思路描述
      • 3.设计实现过程
      • 4.程序性能改进
      • 5.异常处理
      • 6.单元测试展示
      • 7.心路历程和收获

这个作业属于哪个课程https://bbs.csdn.net/forums/ssynkqtd-05
这个作业要求在哪里https://bbs.csdn.net/topics/617294583
这个作业的目标完成一个具有可视化界面的计算器。
其他参考文献

0.页面及功能展示

源代码地址
在这里插入图片描述

1. PSP表格

PSPPersonal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning计划6060
• Estimate• 估计这个任务需要多少时间1515
Development开发700700
• Analysis• 需求分析 (包括学习新技术)100100
• Design Spec• 生成设计文档6060
• Design Review• 设计复审3030
• Coding Standard• 代码规范 (为目前的开发制定合适的规范)3030
• Design• 具体设计6060
• Coding• 具体编码300300
• Code Review• 代码复审4545
• Test• 测试(自我测试,修改代码,提交修改)6060
Reporting报告9090
• Test Repor• 测试报告3030
• Size Measurement• 计算工作量1515
• Postmortem & Process Improvement Plan• 事后总结, 并提出过程改进计划4545
合计850850

2.解题思路描述

  1. 数据结构课上说过,运算式的表达本质是一个栈的过程。因为一个表达式往往会含有非常多的匹配情况(加上三角函数、阶乘等尤其如此,优先级、合不合法等很难判断清楚),所以在一个短暂的工期内想自己实现出一个不出纰漏、完美的轮子是很困难且几乎不可能的。所以后端计算的逻辑有必要用现成的计算库。
  2. 语言的选择,一开始我选用的Go+Fyne图形库的方案。然而因为Go本身GUI的基础薄弱,Fyne库提供的页面也很差强人意。后遂考虑HTML+CSS+JS的方案。中途有考虑过要不要用Go-webview2,把计算逻辑移到Go来做。发现实现较为困难,且有些大材小用,遂放弃。
  3. 原先没学过JS,但听说过精度很差,需要寻找一个精度比较高的计算库来完成计算。

3.设计实现过程

写一个Toy计算器并不是很大的工程,核心思路其实就是创建两个字符串,一个字符串作为显示给用户看的字符串,一个字符串作为最后扔给JS计算库计算的字符串。

var expression = ""; //实际运算的表达式
  1. 整体的HTML结构是一个表单:
<div class="center">
        <h1>$Gorsonpy$ 的 计算器</h1>
        <a href="https://github.com/guuibayer/simple-calculator" target="_blank"><i class="fa fa-github"></i></a>
        <form name="calculator">
            <button type="button" id="clear" class="btn other" value="clear" onclick="clear();">$CE$</button>
            <button type="button" id="clear" class="btn other" value="BACK" onclick="back();"></button>
            <input type="text" id="display">
            <br>
            <input type="button" class="btn number" value="7" onclick="get(this.value);">
            <input type="button" class="btn number" value="8" onclick="get(this.value);">
            <input type="button" class="btn number" value="9" onclick="get(this.value);">
            <input type="button" class="btn operator" value="+" onclick="get(this.value);">
            <input type="button" class="btn operator" value="(" onclick="get(this.value);">
            <input type="button" class="btn operator" value="log" onclick="get_with_left_bracket(this.value);">
            <input type="button" class="btn operator" value="tan" onclick="get_with_left_bracket(this.value);">
            <input type="button" class="btn operator" value="atan" onclick="get_with_left_bracket(this.value);">
            <br>
            <input type="button" class="btn number" value="4" onclick="get(this.value);">
            <input type="button" class="btn number" value="5" onclick="get(this.value);">
            <input type="button" class="btn number" value="6" onclick="get(this.value);">
            <input type="button" class="btn operator" value="*" onclick="get(this.value);">
            <input type="button" class="btn operator" value=")" onclick="get(this.value);">
            <button type="button" class="btn operator" value="x^y" onclick="pow();">$x^y$</button>
            <input type="button" class="btn operator" value="asin" onclick="get_with_left_bracket(this.value);">
            <input type="button" class="btn operator" value="!" 
...
  1. 按钮关联一些函数:
/* recebe os valores */
        function get(value) {
            if (document.getElementById("display").value === errMsg) {
                document.getElementById("display").value = "";
            }
            document.getElementById("display").value += value;
            expression += value;
        }
        function pow() {
            if (document.getElementById("display").value === errMsg) {
                document.getElementById("display").value = "";
            }
            document.getElementById("display").value += "^";
            expression += "^";
        }
        ...
  1. 按下等号的时候计算:
function calculates() {
            document.getElementById("display").value = "";
            var result = "";

            if (expression === "") {
                document.getElementById("display").value = "";
                expression = "";
            } else {
                try {
                    result = math.evaluate(expression, customSymbols);
                } catch (error) {
                    console.error("An error occurred while evaluating the expression: " + error);
                    result = errMsg; // 设置一个错误提示
                }
                document.getElementById("display").value = result;
                expression = "";
            }
        };

4.程序性能改进

主要是选一个好轮子。因为性能的瓶颈一定是在于正则匹配和解析表达式。自己去胡乱优化也不会有什么效果。我选用的是Math.js库而非原生的eval(),因为原生的eval()算的不准,而且会有安全问题,因为eval总是试图解析字符串内容,无论其是否具有危害。

math.config({
            number: 'BigNumber',
            precision: 64,
        });

下面是一个 0.1 + 0.2 = ? 0.1 + 0.2 = ? 0.1+0.2=?的问题,对比一下:
原生的eval:
在这里插入图片描述
math. evaluate:
在这里插入图片描述

5.异常处理

就是在math.evaluate解析的时候catch异常,并赋予用户一个提示信息.此外,对于除0,溢出等情况,evaluate自动会给出一个infinity。

try {
	result = math.evaluate(expression, customSymbols);
} catch (error) {
	console.error("An error occurred while evaluating the expression: " + error);
    result = errMsg; // 设置一个错误提示 
}

6.单元测试展示

在单元测试这里我遇到了一些困难,主要是JS的这个引文件功能实在太bug了?会遇到各种各样难以明说的错误。因为要做单元测试用Jest框架,就要把之前内嵌在html的js文件分离出来,然而这样又会有新的问题,就是js之间互相引用的问题。经过一番折腾我得出一个折中的办法,要做单元测试的时候把文件分离出来做单元测试,要运行的话把js代码贴回去。
因为我的代码很短,所以单元测试很快就做好了:
在这里插入图片描述

test("test add 7 + 8 = 15", () => {
    clearf();
    get(7)
    get("+")
    get(8)
    calculates()
    expect(document.getElementById("display").value).toBe("15")
})

test("test sub 1 - 2 = -1", () => {
    clearf();
    get(1)
    get("-")
    get(2)
    calculates()
    expect(document.getElementById("display").value).toBe("-1")
})
...

7.心路历程和收获

  为了设计一个比较美观的前端页面,我去学习了HTML+CSS+JS这前端三件套。体验到了前端的魅力所在。我学习了如何让自己的代码变得用户友好,能够考虑到各种错误情况并给予用户错误信息,而不是程序崩溃,同时学习了如何对代码做好单元测试。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1054176.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【CVPR 2023】DSVT: Dynamic Sparse Voxel Transformer with Rotated Sets

文章目录 开场白效果意图 重点VoxelNet: End-to-End Learning for Point Cloud Based 3D Object DetectionX-Axis DSVT LayerY-Axis DSVT Layer Dynamic Sparse Window AttentionDynamic set partitionRotated set attention for intra-window feature propagation.Hybrid wind…

Seata详解

前言 ​ 随着互联网技术的不断发展&#xff0c;系统越来越复杂&#xff0c;几乎所有 IT 公司的系统都已经完成从单体架构到分布式架构的转变&#xff0c;分布式系统几乎无处不在&#xff0c;分布式事务由此产生。 事务 ​ 事务是应用程序中一系列严密的操作&#xff0c;所有…

283. 多边形,《算法竞赛进阶指南》,

283. 多边形 - AcWing题库 “多边形游戏”是一款单人益智游戏。 游戏开始时&#xff0c;给定玩家一个具有 N 个顶点 N 条边&#xff08;编号 1∼N&#xff09;的多边形&#xff0c;如图 1 所示&#xff0c;其中 N4 每个顶点上写有一个整数&#xff0c;每个边上标有一个运算符…

2023年中国金刚石工具产量、需求量、市场规模及行业细分产品规模[图]

金刚石工具就是以金刚石为增强体&#xff0c;以金属或聚合物为基体的一类功能复合材料。金刚石工具已经成为当今公认的、唯一有效的硬脆非金属材料加工工具&#xff0c;比如&#xff0c;只有用金刚石刀具能加工超硬的陶瓷&#xff0c;尚无其他代用品。金刚石工具根据其用途的不…

NeurIPS 2023 放榜!3200多篇上榜,录用率26.1%

上周机器学习顶会NeurIPS 2023的接收论文列表公布了&#xff0c;有同学的论文中了嘛&#xff0c;可以评论区分享分享。 这次NeurIPS 2023共录用论文3221篇左右&#xff0c;录用率26.1%&#xff0c;与2022年的25.6%相比还是有所增加的。有想法的同学冲冲冲。 NeurIPS属于CCF A…

C++ 并发编程实战 第八章 设计并发代码 二

目录 8.3 设计数据结构以提升多线程程序的性能 8.3.1 针对复杂操作的数据划分 8.3.2 其他数据结构的访问模式 8.4 设计并发代码时要额外考虑的因素 8.4.1 并行算法代码中的异常安全 8.4.2 可扩展性和Amdahl定律 8.4.3 利用多线程隐藏等待行为 8.4.4 借并发特性改进响应…

ELK整合springboot(第二课)

一、创建一个springboot的项目 pom文件如下&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLo…

Uniapp小程序 时间段选择限制(开始时间 结束时间相互限制)

实现效果&#xff1a; 这里我使用的是uview2.0的DatetimePicker 选择器&#xff0c;实现开始时间与结束时间相互限制的效果&#xff0c;接下来简单看下实现的代码吧&#xff0c;首先看下选择器组件以及相关参数值的初始化 <!-- 时间选择-开始 --> <u-datetime-picker …

【前段基础入门之】=>你不知道的 CSS 选择器的进阶使用!

导语&#xff1a; 在上一章节中&#xff0c;我们了解了 CSS 的一些基本语法概念&#xff0c;那么在这一章节中我们就带来 CSS 选择器知识的分享&#xff0c;选择器这一章的知识点有一点多&#xff0c;不过我们只要认真去理解&#xff0c;学习它也是没什么问题的&#xff0c;还有…

PowerShell 命令窗口执行 pnpm 命令报错 无法加载文件 pnpm.ps1,因为在此系统上禁止运行脚本

目录 问题解决验证附&#xff1a;开源项目微服务商城项目前后端分离项目 问题 在 PowerShell 命令行窗口使用 pnpm run dev 启动 vue3-element-admin 报错&#xff1a; pnpm : 无法加载文件 C:\Users\youlai\AppData\Roaming\npm\pnpm.ps1&#xff0c;因为在此系统上禁止运行脚…

【kubernetes】kubernetes中的Ingress使用

文章目录 1 Service和Endpoint1.1 服务的转发1.2 headless service及其使用场景1.3 服务的类型 2 Ingress3 ingress controller4 IngressClass5 nginx-ingress-controller 1 Service和Endpoint k8s中运行的最小单位是Pod&#xff0c;如果单独运行Pod&#xff0c;没有用控制器进…

假期get新技能?低代码模型应用工具HuggingFists

HuggingFists是什么&#xff1f; HuggingFists是一款研究和使用HuggingFace模型和数据集的AI应用工具。 众所周知&#xff0c;Hugging Face是一家人工智能&#xff08;AI&#xff09;技术公司&#xff0c;致力于开发和推广自然语言处理&#xff08;NLP&#xff09;技术&#xf…

工信部:杭州亚运会开幕式首创 5G 超密组网方案,场馆网络无缝覆盖

“工信 V 报”今日发布消息称&#xff0c;工信部经过精心统筹、周密部署&#xff0c;举全系统之力圆满完成了杭州亚运会开幕式各项保障任务。 据介绍&#xff0c;亚运会的指挥调度、安全保卫、通信网络、计时记分、电视转播等系统顺畅运行&#xff0c;对无线电安全、信息通信服…

《Jetpack Compose从入门到实战》第三章 定制 UI 视图

目录 配置颜色、字体与形状Welcome PageLogin PageHome Page 主题CompositionLocal 配置颜色、字体与形状 -ui.theme.Color.kt val pink100 Color(0xFFFFF1F1) val pink900 Color(0xFF3F2C2C) val white Color(0xFFFFFFFF) val white850 Color(0xD9FFFFFF) val gray Col…

朝着“强国建设民族复兴”之路奋勇前行

今&#xff08;2023年10月1日&#xff09;天&#xff0c;本“人民体验官”隆重推广人民日报官方微博文化产品《人民日报国庆社论#&#xff1a;坚定不移朝着强国建设、民族复兴的宏伟目标奋勇前进》。 图&#xff1a;来源“人民体验官”推广平台 以下推广今天的《人民日报》社论…

深度学习与python theano

文章目录 前言1.安装2.基本用法3.function用法4.shared 变量5.activation function6.Layer层7.regression 回归例子8.classification分类学习9.过拟合10.正则化11.save model12 总结 前言 本章主要介绍深度学习与python theano。 1.安装 2.基本用法 3.function用法 4.sha…

Linux系统编程系列之进程间通信-信号量组

一、什么是信号量组 信号量组是信号量的一种&#xff0c; 是system-V三种IPC对象之一&#xff0c;是进程间通信的一种方式。 二、信号量组的特性 信号量组不是用来传输数据的&#xff0c;而是作为“旗语”&#xff0c;用来协调各进程或者线程工作的。信号量组可以一次性在其内…

【Linux】 OpenSSH_9.3p1 升级到 OpenSSH_9.3p2(亲测无问题,建议收藏)

&#x1f468;‍&#x1f393;博主简介 &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01; &#x1f40b; 希望大家多多支…

基于Python3搭建qt开发环境

Python可视化编程相信大部分刚接触都是tkinter&#xff0c;tkinter是Python自带的库&#xff0c;不需要安装第三方库即可使用&#xff0c;在我的Python专栏中也有很多基于tkinter来设计的可视化界面。本篇文章将尝试另外一个Python的可视化编程库(pyqt)&#xff0c;与tkinter编…

深度剖析Linux磁盘分区 | LVM逻辑卷 | VDO卷 | AutoFS存储自动挂载

深度剖析Linux磁盘分区 | LVM逻辑卷 | VDO卷 | AutoFS存储自动挂载 前言说明1. 安装操作系统分区配置2. 大磁盘分区管理3. LVM逻辑卷管理3.1. 创建LVM逻辑卷3.1.1. 创建物理卷PV3.1.2. 创建卷组VG3.1.3. 创建逻辑卷LV3.1.4. 创建并挂载文件系统3.1.5. 配置开机自动挂载 3.2. 逻…