用Devecostudio写一个简单的计算器
用Devecostudio写一个简单的计算器
//计算器
import { Button1 } from './Button1'
import {Button2} from'./Button2'//定义两个按钮格式
// import {Cal}from'./cal'也可以将四则运算的函数定义到别处然后引入,这里为了方便直接放到这里了
interface Operator {
symbol: string;
precedence: number;
operation: (a: number, b: number) => number;
}
const operators: Operator[] = [
{ symbol: '+', precedence: 1, operation: (a, b) => a + b },
{ symbol: '-', precedence: 1, operation: (a, b) => a - b },
{ symbol: '×', precedence: 2, operation: (a, b) => a * b },
{ symbol: '%', precedence: 2, operation: (a, b) => a / 100 + (b/1000)},
{ symbol: '÷', precedence: 2, operation: (a, b) => a / b }
];
function Cal(expression: string): number {
const tokens = expression.split(' ');
const operand: number[] = [];
const operator: Operator[] = [];
for (const token of tokens) {
if (!isNaN(Number(token))) {
operand.push(Number(token));
} else {
const currentOperator = operators.find(op => op.symbol === token);
if (currentOperator) {
while (operator.length > 0 && operator[operator.length - 1].precedence >= currentOperator.precedence) {
const op = operator.pop()!;
const b = operand.pop()!;
const a = operand.pop()!;
operand.push(op.operation(a, b));
}
operator.push(currentOperator);
}
}
}
while (operator.length > 0) {
const op = operator.pop()!;
const b = operand.pop()!;
const a = operand.pop()!;
operand.push(op.operation(a, b));
}
return operand.pop()!;
}
@Entry
@Component
struct Index{
@State cacu:string=''
@State result:string='0'
build() {
Column({space:10}){
Blank()
Column() {
Text(this.result).fontColor(Color.White).fontSize(50)
.padding({ top: '0.00vp', right: '40.00vp', bottom: '0.00vp', left: '0.00vp' })
}.width('100%').alignItems(HorizontalAlign.End)
Column() {
Text(this.cacu).fontColor(Color.White).fontSize(25)
.padding({ top: '0.00vp', right: '40.00vp', bottom: '0.00vp', left: '0.00vp' })
}.width('100%').alignItems(HorizontalAlign.End).height(40)
Row({space:10}) {
Button1({num:'AC',buttonColor:0xA5A5A5,textColor:Color.Black,textSize:30}).onClick(()=>{
this.cacu=''
this.result='0'
})
Button1({num:'CE',buttonColor:0xA5A5A5,textColor:Color.Black,textSize:30}).onClick(()=>{
this.cacu=this.cacu.slice(0,-1)
})
Button1({num:'%',buttonColor:0xA5A5A5,textColor:Color.Black,textSize:30}).onClick(()=>{
if(this.cacu[this.cacu.length-1]!=' '&&this.cacu[this.cacu.length-1]!='+'&&this.cacu[this.cacu.length-1]!='-'&&this.cacu[this.cacu.length-1]!='.'&&this.cacu[this.cacu.length-1]!='%'&&this.cacu[this.cacu.length-1]!='×'&&this.cacu[this.cacu.length-1]!='÷')
this.cacu=this.cacu+' % '
})
Button1({num:'÷',buttonColor:0xFF9F0B}).onClick(()=>{
if(this.cacu[this.cacu.length-1]!=' '&&this.cacu[this.cacu.length-1]!='+'&&this.cacu[this.cacu.length-1]!='-'&&this.cacu[this.cacu.length-1]!='.'&&this.cacu[this.cacu.length-1]!='%'&&this.cacu[this.cacu.length-1]!='×'&&this.cacu[this.cacu.length-1]!='÷')
this.cacu=this.cacu+' ÷ '
})
}
Row({space:10}) {
Button1({num:'7'}).onClick(()=>{
this.cacu=this.cacu+7
})
Button1({num:'8'}).onClick(()=>{
this.cacu=this.cacu+8
})
Button1({num:'9'}).onClick(()=>{
this.cacu=this.cacu+9
})
Button1({num:'+',buttonColor:0xFF9F0B}).onClick(()=>{
if(this.cacu[this.cacu.length-1]!=' '&&this.cacu[this.cacu.length-1]!='+'&&this.cacu[this.cacu.length-1]!='-'&&this.cacu[this.cacu.length-1]!='.'&&this.cacu[this.cacu.length-1]!='%'&&this.cacu[this.cacu.length-1]!='×'&&this.cacu[this.cacu.length-1]!='÷')
this.cacu=this.cacu+' + '
})
}
Row({space:10}) {
Button1({num:'4'}).onClick(()=>{
this.cacu=this.cacu+4
})
Button1({num:'5'}).onClick(()=>{
this.cacu=this.cacu+5
})
Button1({num:'6'}).onClick(()=>{
this.cacu=this.cacu+6
})
Button1({num:'-',buttonColor:0xFF9F0B}).onClick(()=>{
if(this.cacu[this.cacu.length-1]!=' '&&this.cacu[this.cacu.length-1]!='+'&&this.cacu[this.cacu.length-1]!='-'&&this.cacu[this.cacu.length-1]!='.'&&this.cacu[this.cacu.length-1]!='%'&&this.cacu[this.cacu.length-1]!='×'&&this.cacu[this.cacu.length-1]!='÷')
this.cacu=this.cacu+' - '
})
}
Row({space:10}) {
Button1({num:'1'}).onClick(()=>{
this.cacu=this.cacu+1
})
Button1({num:'2'}).onClick(()=>{
this.cacu=this.cacu+2
})
Button1({num:'3'}).onClick(()=>{
this.cacu=this.cacu+3
})
Button1({num:'×',buttonColor:0xFF9F0B}).onClick(()=>{
if(this.cacu[this.cacu.length-1]!=' '&& this.cacu[this.cacu.length-1]!='+'&& this.cacu[this.cacu.length-1]!='-'&&this.cacu[this.cacu.length-1]!='.'&&this.cacu[this.cacu.length-1]!='%'&&this.cacu[this.cacu.length-1]!='×'&&this.cacu[this.cacu.length-1]!='÷')
this.cacu=this.cacu+' × '
})
}
Row({space:10}){
Button2({num:'0'}).onClick(()=>{
this.cacu=this.cacu+0
})
Button1({num:'.'}).onClick(()=>{
if(this.cacu[this.cacu.length-1]!='+'&&this.cacu[this.cacu.length-1]!='-'&&this.cacu[this.cacu.length-1]!='.'&&this.cacu[this.cacu.length-1]!='%'&&this.cacu[this.cacu.length-1]!='×'&&this.cacu[this.cacu.length-1]!='÷')
this.cacu=this.cacu+'.'
})
Button1({num:'=',buttonColor:0xFF9F0B}).onClick(()=>{
this.result=Cal(this.cacu).toString()
})
}
.margin({ top: '0.00vp', right: '0.00vp', bottom: '40.00vp', left: '0.00vp' })
}.width('100%')
.height('100%')
.backgroundColor(Color.Black)
}
}
//../page/Button1.ets
@Preview
@Component
export struct Button1{
num:string ='1'
buttonColor:number=0X333333
textColor:number=Color.White
textSize:number=40
build() {
Column(){
Text(this.num).fontColor(this.textColor)
.fontSize(this.textSize)
.fontWeight(FontWeight.Medium )
}
.width(75)
.height(75)
.backgroundColor(this.buttonColor)
.justifyContent(FlexAlign.Center)
.borderRadius(37.5)
}
}
//../page/Button2.ets
@Component
export struct Button2{
num:string ='0'
buttonColor:number=0X333333
textColor:number=Color.White
textSize:number=40
build() {
Column(){
Text(`${this.num}`)
.fontColor(this.textColor)
.fontSize(this.textSize)
.fontWeight(FontWeight.Medium )
}
.width(160)
.height(75)
.backgroundColor(this.buttonColor)
.justifyContent(FlexAlign.Center)
.borderRadius(37.5)
}
}
interface Operator {
symbol: string; // 运算符的符号,例如 '+'、'-' 等
precedence: number; // 运算符的优先级,数字越大优先级越高
operation: (a: number, b: number) => number; // 执行运算的函数,接收两个数字作为参数并返回运算结果
}
这里定义了一个名为 Operator 的接口,用于描述运算符的属性。每个运算符具有符号(symbol)、优先级(precedence)和执行运算的函数(operation)。
const operators: Operator[] = [
{ symbol: '+', precedence: 1, operation: (a, b) => a + b },
{ symbol: '-', precedence: 1, operation: (a, b) => a - b },
{ symbol: '×', precedence: 2, operation: (a, b) => a * b },
{ symbol: '%', precedence: 2, operation: (a, b) => a / 100 + (b/1000)},
{ symbol: '÷', precedence: 2, operation: (a, b) => a / b }
];
定义了一个包含四则运算运算符信息的数组 operators。其中,加法和减法的优先级为 1,乘法和除法的优先级为 2。
function Cal(expression: string): number {
const tokens = expression.split(' ');
const operand: number[] = [];
const operator: Operator[] = [];
Cal 函数接受一个字符串表达式作为输入。首先,将表达式按空格分割成标记(tokens)。同时创建了两个栈,一个用于存储操作数(operandStack),一个用于存储运算符(operatorStack)。
for (const token of tokens) {
if (!isNaN(Number(token))) {
operand.push(Number(token));
} else {
const currentOperator = operators.find(op => op.symbol === token);
if (currentOperator) {
while (operator.length > 0 && operator[operator.length - 1].precedence >= currentOperator.precedence) {
const op = operator.pop()!;
const b = operand.pop()!;
const a = operand.pop()!;
operand.push(op.operation(a, b));
}
operator.push(currentOperator);
}
}
}
在遍历标记的循环中,如果标记是一个数字,则将其转换为数字并压入操作数栈。如果标记是一个运算符,先检查运算符栈顶的运算符优先级是否高于或等于当前运算符。如果是,则从运算符栈和操作数栈中取出相应的元素进行运算,并将结果压入操作数栈。然后将当前运算符压入运算符栈。
while (operator.length > 0) {
const op = operator.pop()!;
const b = operand.pop()!;
const a = operand.pop()!;
operand.push(op.operation(a, b));
}
return operand.pop()!;
}
在遍历完所有标记后,如果运算符栈中还有运算符,继续取出进行运算,直到运算符栈为空。最后,返回操作数栈中唯一的结果。总的来说,这个函数实现了对一个四则运算表达式的计算,通过栈来处理运算符的优先级,遵循了常见的表达式求值算法。
例如,对于表达式 3 × 2 + 5 ÷ 2 :
- 首先将
3、2压入operand栈,遇到×时,因为operator栈为空,将其压入。 - 然后将
5、2压入operand栈,遇到+时,由于×的优先级更高,先计算3 × 2 = 6,将结果压入operand栈,再将+压入operator栈。 - 最后处理剩余的
+和÷,计算6 + 2.5 = 8.5并返回。
interface Operator 定义了一个操作符的接口,包含操作符的符号 symbol 、优先级 precedence 以及执行运算的函数 operation 。
- 符号用于标识操作符,如
+、-等。 - 优先级用于确定运算的顺序,数值越大优先级越高。
- 运算函数接受两个数字参数并返回运算结果。
operators 数组定义了一些常见的操作符及其属性和运算逻辑。
- 例如,
+和-的优先级为 1 ,×和÷的优先级为 2 ,%具有特定的运算逻辑。
Cal 函数用于计算给定表达式的值。
tokens = expression.split(' ')将输入的表达式按空格分割成一个个的标记(操作数或操作符)。- 两个栈
operand用于存储操作数,operator用于存储操作符。
遍历标记:
- 如果是数字,将其转换为数字并压入
operand栈。 - 如果是操作符:先查找对应的操作符对象。
- 然后通过比较当前操作符的优先级与栈顶操作符的优先级来决定是否进行运算。
- 如果栈顶操作符的优先级更高或相等,就先取出两个操作数和栈顶操作符进行运算,将结果压入
operand栈。 - 最后将当前操作符压入
operator栈。
遍历完标记后,处理剩余在 operator 栈中的操作符,逐个取出进行运算,直到 operator 栈为空。
最终返回 operand 栈中唯一的结果。
欢迎指正错误
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)