1、简介:
计算器是我们生活中很常见的东西,它可以由多种语言多种方式来实现,今天我想讲的是基于C++语言,由QT实现的可以计算大数的简单计算器。

2、作品演示:
(1)简单四则运算
(2)大数运算

3、重点原理讲解
(1)四则运算如何实现
(2)大数的加减乘除

4、代码主体框架

1个主函数;
两个类:
一个calculator类,实现了对界面的布局,其实这个布局很简单,就设置了一些按钮以及一个显示框。

类的声明:

class calculator : public QMainWindow
{Q_OBJECTpublic:calculator(QWidget *parent = 0);~calculator();private:QLineEdit *inputLine;//显示框QString input="0"; //输入框//0-9按钮QPushButton *zeroButton;QPushButton *oneButton;QPushButton *twoButton;QPushButton *threeButton;QPushButton *fourButton;QPushButton *fiveButton;QPushButton *sixButton;QPushButton *sevenButton;QPushButton *eightButton;QPushButton *nineButton;QPushButton *addButton;QPushButton *subButton;QPushButton *divButton;QPushButton *mulButton;QPushButton *equButton;QPushButton *timButton; //TimeQPushButton *decButton;QPushButton *botButton;QPushButton *CEButton;QPushButton *ACButton;QPushButton *lefButton;QPushButton *rigButton;private slots:void buttonZeroClicked();void buttonOneClicked();void buttonTwoClicked();void buttonThreeClicked();void buttonFourClicked();void buttonFiveClicked();void buttonSixClicked();void buttonSevenClicked();void buttonEightClicked();void buttonNineClicked();void buttonAddClicked();//+void buttonSubClicked();//-void buttonMulClicked();//乘void buttonDivClicked();//除void buttonTimClicked(); //时间void buttonDecClicked();//小数点void buttonBotClicked(); //加减号void buttonEquClicked();//等于号void buttonLefClicked();//左括号void buttonRigClicked();//右括号void buttonCEClicked();//CEvoid buttonACClicked();//AC
};

界面布局:

calculator::calculator(QWidget *parent) : QMainWindow(parent)
{QWidget *widget=new QWidget; //构建一个QWidget布局将设置的布局添加进这个QWidgetthis->setCentralWidget(widget);inputLine=new QLineEdit;inputLine->setText(input);zeroButton=new QPushButton("0");oneButton=new QPushButton("1");twoButton=new QPushButton("2");threeButton=new QPushButton("3");fourButton=new QPushButton("4");fiveButton=new QPushButton("5");sixButton=new QPushButton("6");sevenButton=new QPushButton("7");eightButton=new QPushButton("8");nineButton=new QPushButton("9");decButton=new QPushButton(".");botButton=new QPushButton("±");timButton=new QPushButton("Time");addButton=new QPushButton("+");subButton=new QPushButton("-");mulButton=new QPushButton("*");divButton=new QPushButton("/");equButton=new QPushButton("=");lefButton=new QPushButton("(");rigButton=new QPushButton(")");CEButton=new QPushButton("CE");ACButton=new QPushButton("AC");QGridLayout *H=new QGridLayout(this); //声明了一个网格布局inputLine->setFixedHeight(50); //调整第一行大小CEButton->setFixedHeight(50);ACButton->setFixedHeight(50);H->addWidget(inputLine,0,0,1,3);H->setRowStretch(0,100);H->addWidget(CEButton,0,3);H->addWidget(ACButton,0,4);H->addWidget(oneButton,1,0);H->addWidget(twoButton,1,1);H->addWidget(threeButton,1,2);H->addWidget(botButton,1,3);H->addWidget(timButton,1,4);H->addWidget(fourButton,2,0);H->addWidget(fiveButton,2,1);H->addWidget(sixButton,2,2);H->addWidget(addButton,2,3);H->addWidget(subButton,2,4);H->addWidget(sevenButton,3,0);H->addWidget(eightButton,3,1);H->addWidget(nineButton,3,2);H->addWidget(mulButton,3,3);H->addWidget(divButton,3,4);H->addWidget(zeroButton,4,0);H->addWidget(decButton,4,1);H->addWidget(lefButton,4,2);H->addWidget(rigButton,4,3);H->addWidget(equButton,4,4);widget->setLayout(H); //将布局显示出来connect(zeroButton,SIGNAL(clicked()),this,SLOT(buttonZeroClicked()));//信号与槽函数connect(oneButton,SIGNAL(clicked()),this,SLOT(buttonOneClicked()));connect(twoButton,SIGNAL(clicked()),this,SLOT(buttonTwoClicked()));connect(threeButton,SIGNAL(clicked()),this,SLOT(buttonThreeClicked()));connect(fourButton,SIGNAL(clicked()),this,SLOT(buttonFourClicked()));connect(fiveButton,SIGNAL(clicked()),this,SLOT(buttonFiveClicked()));connect(sixButton,SIGNAL(clicked()),this,SLOT(buttonSixClicked()));connect(sevenButton,SIGNAL(clicked()),this,SLOT(buttonSevenClicked()));connect(eightButton,SIGNAL(clicked()),this,SLOT(buttonEightClicked()));connect(nineButton,SIGNAL(clicked()),this,SLOT(buttonNineClicked()));connect(addButton,SIGNAL(clicked()),this,SLOT(buttonAddClicked()));connect(subButton,SIGNAL(clicked()),this,SLOT(buttonSubClicked()));connect(mulButton,SIGNAL(clicked()),this,SLOT(buttonMulClicked()));connect(divButton,SIGNAL(clicked()),this,SLOT(buttonDivClicked()));connect(botButton,SIGNAL(clicked(bool)),this,SLOT(buttonBotClicked()));//正负号connect(timButton,SIGNAL(clicked(bool)),this,SLOT(buttonTimClicked()));//时间connect(decButton,SIGNAL(clicked(bool)),this,SLOT(buttonDecClicked()));//点号connect(lefButton,SIGNAL(clicked(bool)),this,SLOT(buttonLefClicked()));//左括号connect(rigButton,SIGNAL(clicked(bool)),this,SLOT(buttonRigClicked()));//右括号connect(CEButton,SIGNAL(clicked()),this,SLOT(buttonCEClicked()));connect(ACButton,SIGNAL(clicked()),this,SLOT(buttonACClicked()));connect(equButton,SIGNAL(clicked()),this,SLOT(buttonEquClicked())); //等于号*/}

槽函数实现部分举例说明,其它类似:

void calculator::buttonZeroClicked()  //以下是实现相应的槽函数
{if(input=="0")input='0';else input=input+'0';inputLine->setText(input);
}void calculator::buttonTimClicked() //Time
{input=QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz"); //格式化输出当前时间inputLine->setText(input);
}

点击等于号的时候调用Change函数和Exchange函数,对式子进行运算。

Change 函数,将显示框里面的中缀表达式转化为了后缀表达式,存入OPS字符数组中,数字之间用#分开,保存数组长度,方便后面的运算。

Exchange函数,将后缀表达式进行运算,对每两个数的加法减法乘法或者除法都是采用大数运算,通过CDashu类对 + - * / 的重载,然后在Exchange 函数中建立对象调用,最后将返回值再转化为字符输出到屏幕上。

void calculator::buttonEquClicked()//等于号
{std::string str=input.toStdString();const char *S=str.c_str();cout<<S[strlen(S)];char OPS[max1];int len;double result;char* change = new char[max1];bool flag;Change(S,OPS,len);change = EXchange(OPS,len,result,flag);//QString::number(result,10,6);input=input+"="+change;inputLine->setText(input);
}int Change(const char *S,char OPS[],int &len)
{QStack<char> OPE;int i = 0 ,j = 0;int l = strlen(S);for( i ;i < strlen(S);i++){switch(S[i]){case '+':if(OPE.isEmpty())OPE.push(S[i]);else if(OPE.top() == '*' || OPE.top() == '/' || OPE.top() == '-'){OPS[j++] = OPE.pop();i--;//多次判断OPE.top()符号的优先级是否高于'+'}elseOPE.push(S[i]);break;case '-'://if('('!=S[i-1]&&0!=i)//{if(OPE.isEmpty())OPE.push(S[i]);else if(OPE.top() == '*' || OPE.top() == '/' || OPE.top() == '+'){OPS[j++] = OPE.pop();i--;}elseOPE.push(S[i]);break;//}/*else{while ((S[i] >= '0'&&S[i] <= '9' )|| S[i] == '.'||('-'==S[i]&&(S[i-1]<'0'||S[i-1]>'9' || i == 0))){if(S[i] == '-')OPS[j++]='#';OPS[j++] = S[i];i++;}i--;OPS[j++] = '#';  //数字中的间隔符}*/case '*':if(OPE.isEmpty()){OPE.push(S[i]);}else if(OPE.top() == '/'){OPS[j++] = OPE.pop();i--;}elseOPE.push(S[i]);break;case '/':if(OPE.isEmpty()){OPE.push(S[i]);}else if(OPE.top() == '*'){OPS[j++] = OPE.pop();i--;}elseOPE.push(S[i]);break;case'(':OPE.push(S[i]);break;case')':while (OPE.top() != '('){OPS[j++] = OPE.pop();//遇到右括号,一直弹出操作符知道遇到左括号}OPE.pop();//直接不放入数组弹出左括号break;default:while (S[i] >= '0'&&S[i] <= '9' || S[i] == '.'||('-'==S[i]&&S[i-1]<'0'&&S[i-1]>'9')){OPS[j++] = S[i];i++;}i--;OPS[j++] = '#';  //数字中的间隔符break;}//switch}//forwhile (!OPE.isEmpty()){OPS[j++] = OPE.pop();}len = j;return 0;
}//Changechar* EXchange(char OPS[], int len, double &result,bool &flag)
{int tag = 0,t3;QStack<char*> SZ;char *s = new char[max1];char *str1 = new char[max1];char *str2 = new char[max1];char *str = new char[max1]; char st1[max1][max1];CDashu x1;CDashu x2;CDashu y;int i,j,t = 0,temp;for(i = 0;i < len;i++){switch(OPS[i]){case '+':str1 = SZ.pop();str2 = SZ.pop();x1.Change(str1);x2.Change(str2);y = x2 + x1;tag = 0;temp = 0;if(y.a[0]){s[tag] = y.a[0]+'0';tag++;}elsetemp++;for( ;tag <= y.getlength()-temp;tag++){s[tag] = y.a[tag + temp]+'0';}s[tag] = '\0';SZ.push(s);break;case '-':str1 = SZ.pop();str2 = SZ.pop();x1.Change(str1);x2.Change(str2);y = x2 - x1;tag = 0;temp = 0;if(y.getflag()){s[tag] = '-';tag++;}if(y.a[0]){s[tag] = y.a[0]+'0';tag++;}elsetemp++;if(s[0] == '-'){for( ;tag <= y.getlength();tag++){s[tag] = y.a[tag]+'0';}s[tag] = '\0';}else{for( ;tag <= y.getlength()-temp;tag++){s[tag] = y.a[tag + temp]+'0';}s[tag] = '\0';}SZ.push(s);break;case '*':int max,min,max2;str1 = SZ.pop();str2 = SZ.pop();x1.Change(str1);x2.Change(str2);y = x1*x2;y.get(max,max2,min);j = 0;for(t3 = max;t3 >= min;t3--){s[j++] = y.a[t3]+'0';}s[j] = '\0';SZ.push(s);break;case '/':{str1 = SZ.pop();str2 = SZ.pop();x1.Change(str1);x2.Change(str2);y = x2 / x1;int x = 0;i = 0;int num[max1];while(y.yushu[0]){num[x] = y.yushu[0]%10;y.yushu[0] = y.yushu[0]/10;x++;}x--;while(x > -1){s[i] = num[x]+'0';x--;i++;}s[i] = '.';for(i = i+1,j = 1;j < 50;i++,j++){s[i] = y.yushu[j]+'0';}s[i] = '\0';SZ.push(s);}break;default:j = 0;while (OPS[i] != '#'){st1[t][j] = OPS[i];j++;i++;}st1[t][j] = '\0';SZ.push(st1[t]);t++;break;}}return SZ.top();
}

下面重点介绍一下大数类:

类的声明与部分成员函数的实现

#ifndef CDASHU_H
#define CDASHU_H
#include<cstring>
using namespace std;
#define max1 500
#define MAXN 9999
class CDashu
{
public:int a[max1];int yushu[max1];CDashu() { length = 1; memset(a, 0, sizeof(a)); }   //构造函数void Change( char *s); //将字符串转换为大数long getlength(){return length;}int getflag(){return flag;}friend int Compare(CDashu a,CDashu b);void get(int &m,int &m2,int &min){m = max;m2 = max2;min = this->min;}~CDashu();CDashu operator +(CDashu b);//对各类运算的重载CDashu operator -(CDashu b);CDashu operator *(CDashu b);CDashu operator /(CDashu b);
private:long length;int flag;int max,min,max2;
};#endif // CDASHU_H

大数类的实现:

#include "cdashu.h"#include "cdashu.h"
#include <iostream>
#include <string.h>
using namespace std;
/*
ostream& operator<<(ostream& out, CDashu& b)   //重载输出运算符
{int i;out << b.a[b.length - 1];for (i = b.length - 2; i >= 0; i--){out.width(4);out.fill('0');out << b.a[i];}return out;
}*/
void CDashu::Change( char *s)
{memset(a, 0, sizeof(a));long l = strlen(s);length = l;for (int i = 1; i <= l; i++){a[i] = (int)s[i-1] - '0';}for (int i = 1; i <= l; i++){cout << a[i];}cout << endl;
}
CDashu CDashu::operator+(CDashu b)
{int i = length, j = b.length;if (i >= j){for (; i > 0 && j > 0; i--, j--)a[i] += b.a[j];//逐个相加i = length;for (i; i >= 0; i--){if (a[i] >= 10) //进位运算{a[i - 1] += a[i] / 10;a[i] %= 10;}}return *this;}else{for (; i >= 0 && j >= 0; i--, j--)b.a[j] += a[i];//逐个相加i = b.length;for (i; i > 0; i--){if (b.a[i] >= 10) //进位运算{b.a[i - 1] += b.a[i] / 10;b.a[i] %= 10;}}return b;}}
CDashu CDashu::operator -(CDashu b)
{flag = 0;b.flag = 0;int i, j;if (length == b.length){i = 1;j = 1;while (a[i] == b.a[i]){i++;}if (a[i] < b.a[i])b.flag = 1;}i = length;j = b.length;if (i < j || b.flag){        for (i; i > 0 && j > 0; i--, j--)b.a[j] -= a[i];//一一相减i = b.length;for (i; i > 0; i--){if (b.a[i] < 0) //补位运算{b.a[i] += 10;b.a[i - 1] -= 1;}}return b;}else{for (i; i >= 0 && j >= 0; i--, j--)a[i] -= b.a[j];//一一相减i = length;for (i; i >= 0; i--){if (a[i] < 0) //补位运算{a[i] += 10;a[i - 1] -= 1;}}return *this;}cout << endl;}CDashu CDashu::operator *(CDashu b)
{CDashu t;int i, j;t.max = t.min = t.max2 = 1;for (i = length; i > 0; i--){for (j = b.length; j > 0; j--){t.a[length+b.length+1 -(i + j)] += a[i] * b.a[j];//t.a[]初始化为0t.min = min<(length+b.length+1 -(i + j))?t.min:(length+b.length+1 -(i + j));t.max = max>(length+b.length+1 -(i + j))?t.max:(length+b.length+1 -(i + j));}}for (i = t.min; i <= t.max; i++){if (t.a[i] >= 10){t.a[i + 1] += t.a[i] / 10;t.a[i] = t.a[i] % 10;t.max2 = i+1;}}t.max = t.max > t.max2 ? t.max:t.max2;return t;
}CDashu CDashu::operator /(CDashu b)
{int i,j,flag = 1,count = 0,tag = 0,mm=0;min = 1;flag = Compare(*this,b);max = length;if (length < b.length || flag == 0)count = 0;else{while (flag == 1 || flag == 2){if(min == length && a[min] == 0){break;}else{i = length;j = b.length;count++;for ( ; i >= min && j > 0; i--, j--)a[i] -= b.a[j];//一一相减i = length;for (i; i >= min; i--){if (a[i] < 0) //补位运算{a[i] += 10;a[i - 1] -= 1;}}i = min;if (a[i] == 0 && i != length){while (a[i] == 0){i++;}min = i;}//如果有减到前面为0,最小下标右移到不为0的位置flag = Compare(*this,b);//比较两个数的大小}cout<<count<<endl;}//while}//elsecout << count << '.';yushu[0] = count;tag = 0;for(i = 1;i <= length;i++){if(a[i] != 0){tag = 1;break;}}if(!tag){for(i = 1;i < 50;i++){yushu[i] = 0;}}else{int jingdu = 1;while(jingdu < 50){count = 0;/*if(min == length && a[min] == 0){for( ;jingdu < 30;jingdu++){yushu[jingdu] = 0;}break;}*/length++;a[length] = 0;flag = Compare(*this,b);//比较两个数的大小if(flag == 2){yushu[jingdu] = 1;jingdu++;for( ; jingdu < 50;jingdu++){yushu[jingdu] = 0;}}else{if (flag == 0){yushu[jingdu] = 0;jingdu++;}else{while (flag == 1 || flag==2){if(min == length && a[min] == 0){mm = 1;yushu[jingdu] = count;for( jingdu = jingdu+1;jingdu < 50;jingdu++){yushu[jingdu] = 0;}break;}count++;i = length,j = b.length;for(;i >= min && j > 0;i--,j--){a[i] -= b.a[j];}i = length;for (i; i >= min; i--){if (a[i] < 0) //补位运算{a[i] += 10;a[i - 1] -= 1;}}i = min;if (a[i] == 0 && i != length){while(a[i] == 0){i++;}}min = i;//如果有减到前面为0,最小下标右移到不为0的位置flag = Compare(*this,b);//比较两个数的大小}yushu[jingdu] = count;jingdu++;}}if(mm)break;}}return *this;
}
int Compare(CDashu a,CDashu b)
{int i = a.min, j = 1,flag = 1;if(a.length-a.min + 1 < b.length)flag = 0;else if(a.length-a.min+1 > b.length)flag = 1;else{while (a.a[i] == b.a[j] && i <= a.length && j <= b.length){i++;j++;}if (a.a[i] < b.a[j])flag = 0;if(a.a[i] == b.a[i]){flag = 2;}}return flag;
}CDashu::~CDashu()
{}

QT计算器 之 大数运算相关推荐

  1. QT 计算器练习(字符串运算)

    QT 计算器练习(字符串运算) 一.简述 记-计算器练习.字符串的"加减乘除"操作. 例子打包:链接: https://pan.baidu.com/s/1BjP-tmu5bafJv ...

  2. 基于C++的Qt计算器

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.设计计算器界面 二.代码分析 1. 2. 总结 前言 本文是基于C++开发Qt计算器,实现功能有利用鼠标按下数字和 ...

  3. C语言实现大数运算(长整数的加、减、乘、除)

    由于整型数的位数有限,因此整型数不能满足大整数(超长整数)的运算要求 .大整数计算是利用字符串来表示大整数,即用字符串的一位字符表示大整数的一位数值,然后根据四则运算规则实现大整数的四则运算. 简单表 ...

  4. Qt计算器开发(二):信号槽实现数学表达式合法性检查

    表达式的合法性 由于我们的计算器不是单步计算的,所以我们能够一次性输入一个长表达式.然而假设用户输入的长表达式不合法的话,那么就会引发灾难.所以有必要对于用户的输入做一个限制. 一些限制举例: 比方, ...

  5. C语言学习趣事_之_大数运算_加法

    C语言学习趣事_大数运算_之加法 1.引子    在C语言中,因为预定义的自然数类型的大小是有上下限度的,这就决定了在进行数的运算的时候,必然受到限制,同时因为C语言是最接近汇编的一种程序设计语言,并 ...

  6. java中大数开方_Java中的大数运算

    # 一:大数运算出现的背景 java里面整型int与浮点型float,double它们存放数据的范围是有限的,当出行更大的数值时会发生溢出. 最典型的场景是金融行业,直接使用单精度或者双精浮点数来表示 ...

  7. Openssl 之大数运算函数 BN

    Openssl 之大数运算函数 BN 主要介绍Openssl中的有关大数运算函数,这个对于RSA研究和实现比较有价值   1.初始化函数 BIGNUM *BN_new(void);    新生成一个B ...

  8. 【PAT甲级 大数运算】1065 A+B and C (64bit) (20 分) Python 全部AC

    题目 初学python,第一次用python刷oj,挑了个简单题试试手. 在大数运算方面,python没有数的大小限制,简直开挂. total = int(input()) for i in rang ...

  9. Java的学习与java大数运算

    之前就学过一点java,但太久没用知识点早就还给书本,之前在实验室搞到一本java的书,今天来重新温习一下 java的语法大部分和c++语言是一样的,入门非常快,所以在这里基础语句的用法就省略了 输出 ...

最新文章

  1. ASP.NET 2.0 页面编译方式
  2. 在ubuntu下安显卡驱动
  3. Python运维开发基础01-语法基础【转】
  4. 一些C语言学习的国外资源
  5. 程矢Axure夜话:Axure手机原型视频教程之中继器上下滑动加载更多
  6. Winform字体统一方案
  7. 微型计算机及接口技术笔记,微机原理与接口技术笔记(一)
  8. maven 常量字符串过长_从基于Maven的Web应用程序获取版本字符串
  9. mysql 函数重载_[赋值]函数,变量,重载 ,_第1页_169IT
  10. LeetCode 1848. 到目标元素的最小距离
  11. MongoDB Shell和Robo3T使用以及与SQL语法比较
  12. 从前序与中序遍历序列构造二叉树
  13. mysql报错:Host ***.***.***.*** is not allowed to connect to this MySQL server
  14. Beego 使用笔记
  15. ts找不到primeng/primeng
  16. android源码编译1
  17. python模糊图像判断
  18. vue路由守卫beforeEach和afterEach
  19. 大数据时代网络安全分析
  20. 当男人出现这2种状态时,女人一定要当心

热门文章

  1. shell alias命令,给命令设置别名
  2. linux中如何压缩目录文件,如何在Linux中压缩文件和目录
  3. pytorch----深度学习中学习率的衰减策略
  4. 软件工程的事实与谬误
  5. 联想小新潮7000如何bios设置u盘启动操作
  6. 用js使鼠标变成小手状
  7. batchnorm原理及代码详解(笔记2)
  8. 冷热分离之OTS表格存储实战
  9. 开源全文搜索引擎MeiliSearch
  10. 酷睿i7 1260p和i7 1280p差距 选哪个好