好资料,51黑有你更精彩!!!楼主的主程序:
- #include "yunsuan.h"
- u8 jshcq[16]={0}; //计算结果缓存区
- _SU shushu1={0,0,{0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; //前数
- _SU shushu2={0,0,{0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; //后数
- extern u8 da; //定义静态变量da,对应LCD显示字符位置
- /**********************************************
- *功能:LCD显示数组清零
- **********************************************/
- void Lcd_qinpin(void)
- {
- u8 i; //定义变量i
- for(i=0;i<16;i++){ //循环16次
- lcdxs[i]=' '; //LCD显示字符数组清空
- }
- }
- /**********************************************************************************************************************************
- *功能:LCD输入显示算式限制函数
- 目的:限制字符的输入显示。
- 情况分析:1、两个数首位都不能是无意义的0。 例如,00.12。
- 2、两个数的小数点最多都只能有1个。例如,12.3.4。
- 3、两个数首位只能是数字。 例如,.5898。
- 4、两个数尾位都不能是无效的0。 例如,65.30。
- 5、算式中运算符必须有1个。 例如,567。
- (情况分析后补,具体看程序)
- zhuangtai对应位说明:
- bit[2-0] : 前个显示字符对应的标号(fenzu)。
- bit[3] : 0)当前输入数首位数字不是0, 1)当前输入数首位数字是0。
- bit[4] : 0)字符不显示, 1)显示字符。
- bit[5] : 0)算式后数没小数点, 1)算式后数有小数点。
- bit[6] : 0)算式前数没小数点, 1)算式前数有小数点。
- bit[7] : 0)当前算式没有输入过运算符, 1)当前算式有输入过运算符。
- 输入算式满了的情况下,只能按等号键有效,通过da判断实现。
- **********************************************************************************************************************************/
- u8 Shizhe_Xianzhi(u8 x)
- {
- static u8 zhuangtai=0x04; //给定zhuangtai的初值0x04,为什么是0x04?分析知道首位的限制情况和前一个字符是运算符类似
- u8 fenzu=0; //定义变量fenzu,作用如下
- //-------------给输入按键情况分类-------------
- if(x=='0'){ //输入'0'
- if(da<16){
- fenzu=1; //fenzu=1
- }
- }else{
- if(x>'0'){
- if(x=='='){ //输入'='
- fenzu=5; //fenzu=5
- }else{ //输入'123456789'
- if(da<16){
- fenzu=2; //fenzu=2
- }
- }
- }else{
- if(x=='.'){ //输入'.'
- if(da<16){
- fenzu=3; //fenzu=3
- }
- }else{ //输入'+-*/'
- if(da<16){
- fenzu=4; //fenzu=4
- }
- }
- }
- }
- zhuangtai&=0xef; //zhuangtai字符显示标志位置0
- //---------------------按等号键的后续处理-----------------------------------------
- if((zhuangtai&0x07)==0x06){ //上一个状态是清除'='按下
- zhuangtai=0x04; //zhuangtai恢复初始值
- }
- if((zhuangtai&0x07)==0x05){ //上一个状态是计算'='按下
- if(fenzu==5){ //计算完算式,需再次按'='清屏处理,不然不执行任何操作
- zhuangtai=0x06; //zhuangtai恢复初始值
- zhuangtai|=0x10; //zhuangtai字符显示标志位置1
- return zhuangtai; //跳出准备执行清屏与相关数据初始化工作
- }else{
- return zhuangtai; //跳出,无操作
- }
- }
- //-------------------------------------按fenzu分类处理--------------------------------------------------------------------------
- switch(fenzu)
- {
- case 1:
- if((zhuangtai&0x0f)!=0x09){ //排除一种情况:当前输入数首位数字是0,并且前一个字符是'0'
- if((zhuangtai&0x07)==0x04){ //两种情况:刚开始输入、前一个字符是运算符
- zhuangtai|=0x08; //zhuangtai第3位置位
- }
- zhuangtai&=0xf8; //zhuangtai清零后3位
- zhuangtai|=0x11; //zhuangtai字符显示标志位置1、zhuangtai添加后3位状态值(1)
- }
- break;
- case 2:
- if((zhuangtai&0x0f)!=0x09){ //排除一种情况:当前输入数首位数字是0,并且前一个字符是'0'
- zhuangtai&=0xf8; //zhuangtai清零后3位
- zhuangtai|=0x12; //zhuangtai字符显示标志位置1、zhuangtai添加后3位状态值(2)
- }
- break;
- case 3:
- //排除情况:前一个字符是小数点、前一个字符是运算符、当前算式有小数点没有运算符、当前算式有运算符有小数点
- if(((zhuangtai&0x07)!=0x03)&&((zhuangtai&0x07)!=0x04)&&((zhuangtai&0xc0)!=0x40)&&((zhuangtai&0xa0)!=0xa0)){
- zhuangtai&=0xf8; //zhuangtai清零后3位
- if(zhuangtai&0x80){ //当前算式有运算符
- zhuangtai|=0x20; //zhuangtai第5位置位
- }else{ //当前算式没有运算符
- zhuangtai|=0x40; //zhuangtai第6位置位
- }
- zhuangtai&=0xf7; //zhuangtai第3位(首位数字0标志位)清零(有小数点后,首位是不是0,对输入数字字符没影响)
- zhuangtai|=0x13; //zhuangtai字符显示标志位置1、zhuangtai添加后3位状态值(3)
- }
- break;
- case 4:
- //排除情况:前一个字符是小数点、前一个字符是运算符、前数有小数点前一个字符是0、算式输入过一次运算符
- if(((zhuangtai&0x07)!=0x03)&&((zhuangtai&0x07)!=0x04)&&((zhuangtai&0xc7)!=0x41)&&((zhuangtai&0x80)!=0x80)){
- zhuangtai&=0xf8; //zhuangtai清零后3位
- zhuangtai&=0xf7; //zhuangtai第3位(首位数字0标志位)清零
- zhuangtai|=0x94; //zhuangtai字符显示标志位置1、zhuangtai第7位置位、zhuangtai添加后3位状态值(4)
- }
- break;
- case 5:
- //排除情况:前一个字符是小数点、前一个字符是运算符、后数有小数点前一个字符是0、算式没输入过运算符
- if(((zhuangtai&0x07)!=0x03)&&((zhuangtai&0x07)!=0x04)&&((zhuangtai&0xa7)!=0xa1)&&(zhuangtai&0x80)){
- zhuangtai&=0xf8; //zhuangtai清零后3位
- zhuangtai|=0x15; //zhuangtai字符显示标志位置1、zhuangtai添加后3位状态值(5)
- }else{
- //输入算式不合理的情况下
- zhuangtai=0x16; //zhuangtai字符显示标志位置1、zhuangtai添加后3位状态值(6)
- }
- break;
- default:
- break;
- }
- //--------------------------------------------------------------------------------------------------------------------------------
- return zhuangtai; //返回按键状态值
- }
- /**********************************************************************************************************
- *功能:结构体数据随输入字符改变
- 目的:随着输入字符,改变相应的结构体数据(用于四则运算)。
- 具体情况:记录,shushu1.zscd //前数整数个数
- shushu1.sscd //前数小数个数
- shushu1.shujuabc[] //去除小数点后的前数数据
- shushu2.zscd //后数整数个数
- shushu2.sscd //后数小数个数
- shushu2.shujuabc[] //去除小数点后的后数数据
- **********************************************************************************************************/
- void Jiegou_Chuli(u8 xcu)
- {
- static u8 i=0,xs=0,ys=0; //定义变量i对应shujuabc[]标号,变量xs对应小数点,变量ys对应运算符
- if(xcu!='='){ //按下的不是等号键
- if(xcu>='0'){ //输入数字
- if(xs==0){
- if(ys==0){ //(输入算式没小数点、没运算符)前数整数部分
- shushu1.zscd++; //前数整数对应个数加一
- shushu1.shujuabc[i]=xcu-0x30; //输入字符数字存入shushu1.shujuabc[]
- }else{ //(输入算式没小数点、有运算符)后数整数部分
- shushu2.zscd++; //后数整数对应个数加一
- shushu2.shujuabc[i]=xcu-0x30; //输入字符数字存入shushu2.shujuabc[]
- }
- }else{
- if(xs==1){
- if(ys==0){ //(输入算式有一个小数点、没运算符)前数小数部分
- shushu1.sscd++; //前数小数对应个数加一
- shushu1.shujuabc[i]=xcu-0x30; //输入字符数字存入shushu1.shujuabc[]
- }else{ //(输入算式前数有小数点、有运算符)后数整数部分
- shushu2.zscd++; //后数整数对应个数加一
- shushu2.shujuabc[i]=xcu-0x30; //输入字符数字存入shushu2.shujuabc[]
- }
- }else{ //(输入算式后数有小数点、有运算符)后数小数部分
- shushu2.sscd++; //后数小数对应个数加一
- shushu2.shujuabc[i]=xcu-0x30; //输入字符数字存入shushu2.shujuabc[]
- }
- }
- i++; //变量i加一
- }else{
- if(xcu=='.'){ //是小数点
- if(ys==0){ //当前没有运算符
- xs=1; //xs=1,表示前数有小数点了
- }else{ //当前有运算符
- xs=2; //xs=2,表示后数有小数点了
- }
- }else{ //是运算符
- i=0; //变量i置零,开始对应后数存储数组shujuabc[]
- ys=1; //ys=1,表示运算符有了
- }
- }
- }else{ //按下的是等号键
- i=0; //变量初始化,准备下次运算
- xs=0;
- ys=0;
- }
- }
- /*********************************************************************************************
- *功能:结构体数据初始化
- 目的:结构体数据和计算结果存储数组初始化,为下次运算准备。
- *********************************************************************************************/
- void Jiegou_Csh(void)
- {
- //---------初始化结构体数据和计算结果存储数组---------
- u8 i; //定义变量i
- shushu1.zscd=0; //前数整数个数置零
- shushu1.sscd=0; //前数小数个数置零
- shushu2.zscd=0; //后数整数个数置零
- shushu2.sscd=0; //后数小数个数置零
- for(i=0;i<14;i++){ //循环14次
- shushu1.shujuabc[i]=0; //前数数据清零
- shushu2.shujuabc[i]=0; //后数数据清零
- jshcq[i]=0; //计算结果存储数组前14位清零
- }
- jshcq[14]=0; //计算结果存储数组15位清零
- jshcq[15]=0; //计算结果存储数组16位清零
- }
- /********************************************************************************************************************
- *功能:运算符判断
- 目的:以运算符分类处理四则运算。
- ********************************************************************************************************************/
- u8 Yunsf_Jl(void)
- {
- u8 ysf; //ysf用作运算符记录
- if(shushu1.sscd==0){ //没有小数部分
- ysf=lcdxs[shushu1.zscd]; //前数的整数部分长度就是运算符在lcdxs[]中的位置
- }else{ //有小数部分
- ysf=lcdxs[shushu1.zscd+shushu1.sscd+1]; //前数的整数部分加前数的小数部分长度再加小数位就是运算符在lcdxs[]中的位置
- }
- return ysf; //返回ysf
- }
- /**********************************************************************************************************************************************************
- *功能:乘法函数
- **********************************************************************************************************************************************************/
- u8 Chengfa(void)
- {
- u8 ic=0,jc=0,nc=0,mc=0; //前数开始运算位,后数开始运算位,计算结果存储位置变量,计算结果存储起始位
- ic=shushu1.zscd+shushu1.sscd-1; //赋值“前数的的尾位在shushu1.shujuabc[]中的位置”给ic
- jc=shushu2.zscd+shushu2.sscd-1; //赋值“后数的的尾位在shushu2.shujuabc[]中的位置”给jc
- if(((ic==0)&&(shushu1.shujuabc[ic]==0))||((jc==0)&&(shushu2.shujuabc[jc]==0))){ //前数和后数中至少一个是0
- jshcq[0]=0; //显示计算结果'0'
- return 0xf0; //跳出
- }
- //----------------------------循环0---------------------------------------------------------
- do
- {
- jshcq[nc]+=shushu2.shujuabc[jc]*shushu1.shujuabc[ic]; //存储两数运算结果
- if(jshcq[nc]>9){ //两数运算结果是2位数
- jshcq[nc+1]+=jshcq[nc]/10; //高位累加进位
- jshcq[nc]%=10; //低位取个位
- }
- if(ic!=0){ //前数数据没取完
- ic--; //前数运算位左移
- nc++; //运算结果存储位右移
- }else{ //前数数据取完了
- if(jc!=0){ //后数数据没取完
- ic=shushu1.zscd+shushu1.sscd-1; //前数起始位初始值
- jc--; //后数运算位左移
- mc++; //存储结果起始位右移
- nc=mc; //赋值给nc
- }else{ //后数数据取完了
- if(jshcq[nc+1]!=0){ //如果计算完有进位
- nc++; //相应的nc加一
- }
- break; //跳出循环 <<<====(循环0,出口)
- }
- }
- }while(1);
- //--------------------------------------------------------------------------------------------
- jc=15; //jc赋值15,作用不同上面
- if((shushu1.sscd!=0)||(shushu2.sscd!=0)){ //前数和后数中至少有一个有小数点
- jc=nc-(shushu1.sscd+shushu2.sscd); //计算结果总长度(不算小数点)-两个数小数部分长度和。jc是小数点在lcdxs[]中的位置
- }
- mc=(jc<<4)+nc; //高四位存小数点位,低四位存计算结果长度
- return mc; //带出mc
- }
- /***************************************************************************************************************************************
- *功能:加法函数
- ***************************************************************************************************************************************/
- u8 Jiafa(void)
- {
- u8 ic=0,jc=0,nc=0,mc=0; //前数开始运算位,后数开始运算位,计算结果存储位置变量,计算结果存储起始位
- ic=shushu1.zscd+shushu1.sscd-1; //赋值“前数的的尾位在shushu1.shujuabc[]中的位置”给ic
- jc=shushu2.zscd+shushu2.sscd-1; //赋值“后数的的尾位在shushu2.shujuabc[]中的位置”给jc
- //-------------------处理前数和后数小数位较长的部分--------------------------
- if(shushu1.sscd>shushu2.sscd){ //前数的小数部分比后数的小数部分长
- do
- {
- if(ic-shushu1.zscd==jc-shushu2.zscd){ //直到取到小数位一样长后
- break; //跳出 <<<====(出口)
- }else{
- jshcq[nc]+=shushu1.shujuabc[ic]; //小数位长的直接赋值给jshcq[]
- nc++; //存储位递加
- ic--; //移位取下一位小数位
- }
- }while(1);
- mc=shushu1.sscd; //小数点位置计算用到
- }else{
- if(shushu1.sscd!=shushu2.sscd){ //小数位等长不用处理
- do
- {
- if(ic-shushu1.zscd==jc-shushu2.zscd){ //直到取到小数位一样长后
- break; //跳出 <<<====(出口)
- }else{
- jshcq[nc]+=shushu2.shujuabc[jc]; //小数位长的直接赋值给jshcq[]
- nc++; //存储位递加
- jc--; //移位取下一位小数位
- }
- }while(1);
- }
- mc=shushu2.sscd; //小数点位置计算用到
- }
- //-------------------处理另一部分--------------------------------------------------
- do
- {
- jshcq[nc]+=shushu1.shujuabc[ic]+shushu2.shujuabc[jc]; //两数中间部分相加
- if(jshcq[nc]>9){ //两数运算结果是2位数
- jshcq[nc+1]+=jshcq[nc]/10; //高位累加进位
- jshcq[nc]%=10; //低位取个位
- }
- if((ic!=0)&&(jc!=0)){ //两个数数据都没取完
- nc++;
- ic--;
- jc--;
- }else{
- if((ic==0)&&(jc==0)){ //两个数数据都取完
- break; //跳出 <<<====(出口)
- }else{
- if(ic==0){ //前数数据取完
- //-------------------后数整数部分长出的部分处理---------------------------
- do{
- if(jc==0){
- break; //跳出 <<<====(出口)
- }else{
- nc++;
- jc--;
- }
- jshcq[nc]+=shushu2.shujuabc[jc]; //后数整数长的部分再取
- if(jshcq[nc]>9){ //两数运算结果是2位数
- jshcq[nc+1]+=jshcq[nc]/10; //高位累加进位
- jshcq[nc]%=10; //低位取个位
- }
- }while(1);
- //------------------------------------------------------------------------
- }else{ //后数数据取完
- //-------------------前数整数部分长出的部分处理---------------------------
- do{
- if(ic==0){
- break; //跳出 <<<====(出口)
- }else{
- nc++;
- ic--;
- }
- jshcq[nc]+=shushu1.shujuabc[ic]; //前数整数长的部分再取
- if(jshcq[nc]>9){ //两数运算结果是2位数
- jshcq[nc+1]+=jshcq[nc]/10; //高位累加进位
- jshcq[nc]%=10; //低位取个位
- }
- }while(1);
- //------------------------------------------------------------------------
- }
- break; //跳出
- }
- }
- }while(1);
- if(jshcq[nc+1]>0){ //高位有进位的情况
- nc++;
- }
- //------------------------------------------------------------------------------------
- jc=15;
- if((shushu1.sscd!=0)||(shushu2.sscd!=0)){
- jc=nc-mc; //计算结果总长度(不算小数点)-小数部分长度。小数点在lcdxs[]中的位置
- }
- mc=(jc<<4)+nc; //高四位存小数点位,低四位存计算结果长度
- return mc;
- }
- /******************************************************************************************************************************************
- *功能:减法函数
- ******************************************************************************************************************************************/
- u8 Jianfa(void)
- {
- u8 ic=0,jc=0,nc=0,mc=0;
- //-----------------------------比较前数和后数的大小---------------------------------------------------------------------
- if(shushu1.zscd>shushu2.zscd){ //前数整数部分比后数整数部分长
- mc=1; //前数比后数大
- }else{
- if(shushu1.zscd!=shushu2.zscd){ //前数整数部分比后数整数部分短
- mc=2; //后数比前数大
- }else{ //前数整数部分和后数整数部分一样长
- do
- {
- if(shushu1.shujuabc[ic]>shushu2.shujuabc[jc]){ //前数高位比后数高位大
- mc=1;
- break; //跳出
- }else{
- if(shushu1.shujuabc[ic]!=shushu2.shujuabc[jc]){ //前数高位比后数高位小
- mc=2;
- break; //跳出
- }else{ //前数高位和后数高位一样大
- if((ic!=shushu1.zscd+shushu1.sscd-1)&&(jc!=shushu2.zscd+shushu2.sscd-1)){ //前数和后数数据都没有取完
- ic++;
- jc++;
- }else{
- if((ic==shushu1.zscd+shushu1.sscd-1)&&(jc==shushu2.zscd+shushu2.sscd-1)){ //前数和后数数据都取完
- mc=0; //前数和后数一样大
- break; //跳出
- }else{
- if(ic==shushu1.zscd+shushu1.sscd-1){ //前数数据取完,后数没取完
- mc=2;
- break; //跳出
- }else{ //后数数据取完,前数没取完
- mc=1;
- break; //跳出
- }
- }
- }
- }
- }
- }while(1);
- }
- }
- //-----------------------------------------------------------------------------------------------------------------------
- ic=shushu1.zscd+shushu1.sscd-1;
- jc=shushu2.zscd+shushu2.sscd-1;
- switch(mc)
- {
- case 0:
- jshcq[0]=0; //显示计算结果'0'
- break;
- case 1: //与下面mc=2是一样的,下面备注详细点
- if(shushu1.sscd>=shushu2.sscd){ //前数不比后数小数部分短
- do
- {
- if(ic-shushu1.zscd==jc-shushu2.zscd){ //直到取到小数位一样长后
- break; //跳出
- }else{
- jshcq[nc]=shushu1.shujuabc[ic]; //小数位长的直接赋值给jshcq[]
- nc++; //存储位递加
- ic--; //移位取下一位小数位
- }
- }while(1);
- }else{ //前数比后数小数部分短
- shushu1.shujuabc[ic]--; //减一
- jshcq[nc]=10-shushu2.shujuabc[jc];
- nc++;
- jc--;
- do
- {
- if(ic-shushu1.zscd==jc-shushu2.zscd){ //直到取到小数位一样长后
- break; //跳出
- }else{
- jshcq[nc]=9-shushu2.shujuabc[jc];
- nc++; //存储位递加
- jc--; //移位取下一位小数位
- }
- }while(1);
- }
- do
- {
- if(shushu1.shujuabc[ic]>=shushu2.shujuabc[jc]){ //前数不比后数小
- jshcq[nc]+=shushu1.shujuabc[ic]-shushu2.shujuabc[jc]; //前数-后数
- if(jc==0){ //后数取完了
- do
- {
- if(ic!=0){ //前数没取完
- nc++;
- ic--;
- }else{
- break;
- }
- jshcq[nc]+=shushu1.shujuabc[ic];
- }while(1);
- break; //前数取完跳出循环
- }else{
- ic--;
- jc--;
- nc++;
- }
- }else{ //前数比后数小
- shushu1.shujuabc[ic]+=10; //加10
- if(shushu1.shujuabc[ic-1]!=0){ //当前运算前数的前一位不等于0
- shushu1.shujuabc[ic-1]--; //减一位
-
- }else{ //当前运算前数的前一位等于0
- mc=ic; //mc的作用变了
- ic--;
- do
- {
- shushu1.shujuabc[ic]=9; //0位置9
- if(shushu1.shujuabc[ic-1]!=0){ //找可以减的位
- shushu1.shujuabc[ic-1]--; //减一
- break; //跳出
- }else{ //再找
- ic--;
- }
- }while(1);
- ic=mc;
- }
- }
- }while(1);
- break;
- case 2:
- if(shushu2.sscd>=shushu1.sscd){ //后数不比前数小数部分短 <<<=====(分情况实现)
- //---------------------------------------------------------------------------------------------------
- do
- {
- if(ic-shushu1.zscd==jc-shushu2.zscd){ //直到取到小数位一样长后 <<<=====(目的)
- break; //跳出
- }else{
- jshcq[nc]=shushu2.shujuabc[jc]; //小数位长的直接赋值给jshcq[]
- nc++; //存储位递加
- jc--; //移位取下一位小数位
- }
- }while(1);
- //---------------------------------------------------------------------------------------------------
- }else{ //后数比前数小数部分短
- //--------------------------------------------------------------------------------------------------
- shushu2.shujuabc[jc]--; //减一
- jshcq[nc]=10-shushu1.shujuabc[ic];
- nc++;
- ic--;
- do
- {
- if(ic-shushu1.zscd==jc-shushu2.zscd){ //直到取到小数位一样长后 <<<=====(目的)
- break; //跳出
- }else{
- jshcq[nc]=9-shushu1.shujuabc[ic];
- nc++; //存储位递加
- ic--; //移位取下一位小数位
- }
- }while(1);
- //--------------------------------------------------------------------------------------------------
- }
- //-----------------------------循环0-------------------------------------------------------------------
- do
- {
- if(shushu2.shujuabc[jc]>=shushu1.shujuabc[ic]){ //后数不比前数小
- jshcq[nc]+=shushu2.shujuabc[jc]-shushu1.shujuabc[ic]; //后数-前数
- if(ic==0){ //前数取完了
- //------------------------循环2-----------------------------------------------------
- do
- {
- if(jc!=0){ //后数没取完
- nc++;
- jc--;
- }else{ //后数取完了
- break; //跳出 <<<====(循环2,出口)
- }
- jshcq[nc]+=shushu2.shujuabc[jc];
- }while(1);
- //----------------------------------------------------------------------------------
- nc++;
- jshcq[nc]='-'-0x30; //负号先记上
- break; //后数取完跳出循环 <<<=====(循环0,出口)
- }else{
- ic--;
- jc--;
- nc++;
- }
- }else{ //后数比前数小
- shushu2.shujuabc[jc]+=10; //加10
- if(shushu2.shujuabc[jc-1]!=0){ //当前运算后数的前一位不等于0
- shushu2.shujuabc[jc-1]--; //减一位
-
- }else{ //当前运算后数的前一位等于0
- //-------------------------------循环1---------------------------------------------------------
- mc=jc; //mc的作用变了
- jc--;
- do
- {
- shushu2.shujuabc[jc]=9; //0位置9
- if(shushu2.shujuabc[jc-1]!=0){ //找可以减的位
- shushu2.shujuabc[jc-1]--; //不够减,高位要 <<<=====(循环1,目的)
- break; //跳出
- }else{ //再找
- ic--;
- }
- }while(1);
- jc=mc;
- //---------------------------------------------------------------------------------------------
- }
- }
- }while(1);
- //-----------------------------------------------------------------------------------------------------
- break;
- default:
- break;
- }
- jc=15;
- if(shushu1.sscd>=shushu2.sscd){ //没有多余变量可以利用,只能再判断一次小数部分长短
- mc=shushu1.sscd;
- }else{
- mc=shushu2.sscd;
- }
- if((shushu1.sscd!=0)||(shushu2.sscd!=0)){
- jc=nc-mc; //计算结果总长度(不算小数点)-小数部分长度。小数点在lcdxs[]中的位置
- }
- mc=(jc<<4)+nc; //高四位存小数点位,低四位存计算结果长度
- return mc;
- }
- /*********************************************************************************************************
- *功能:除法函数
- *********************************************************************************************************/
- u8 Chufa(void)
- {
- u8 ic=0,jc=0,nc=0,mc=0,gc=0,xc=0;
- //--------------------------------特殊情况处理-----------------------------------------------------------
- if((shushu2.shujuabc[0]==0)&&(shushu2.zscd==1)&&(shushu2.sscd==0)){ //后数是0的情况,不进行运算
- Lcd_qinpin(); //LCD显示数组清零
- lcdxs[0]='x'; //无法计算结果
- return 0xff;
- }
- if((shushu1.shujuabc[0]==0)&&(shushu1.zscd==1)&&(shushu1.sscd==0)){ //前数是0的情况
- Lcd_qinpin(); //LCD显示数组清零,准备存储计算结果
- lcdxs[0]='0'; //计算结果是0
- return 0xff;
- }
- //--------------------------------------------------------------------------------------------------------
- while(shushu1.shujuabc[ic]==0){ //前数是0的位不用运算
- ic++;
- }
- while(shushu2.shujuabc[jc]==0){ //后数是0的位不用运算
- jc++;
- }
- xc=shushu2.zscd-shushu1.zscd+ic-jc+15; //小数点位置
- mc=jc<<4; //当前jc值存入mc高四位,jc最大13,4位足以存储
- //---------------------------------大循环0号,直到计算出16位计算结果才跳出------------------------------------------------
- do
- {
- mc&=0xf0; //清除低四位
- mc|=ic; //记录ic的值,存入mc低四位 (关键点:mc之前的数据一定是0)
- if(nc!=16){ //计算结果没满16位
- if((mc&0x0f)>=14-shushu2.zscd-shushu2.sscd){ //“前数截取部分的长度首位置之后的剩余的长度”不会比“后数的长度”长
- //----------------------------------循环1号,为了能计算出足有16位的结果----------------------------------------------
- jc=0; //这里jc的作用是一个起始值为0的变量
- do
- {
- shushu1.shujuabc[jc]=shushu1.shujuabc[ic]; //将剩余的有效数字重新以shushu1.shujuabc[0]为起始顺序存储
- shushu1.shujuabc[ic]=0; //清除
- if(ic==13){ //数据重存完
- break; //跳出
- }else{ //继续转存有效数据
- jc++;
- ic++;
- }
- }while(1);
- ic=0; //相应的变量值也将改变,实现一个14位数据的数组当一个28位数据的数组使用 <<<====(循环1号,目的)
- mc&=0xf0; //清除低四位,mc低四位清零,同步ic值
- jc=mc>>4; //jc恢复初始值
- //-----------------------------------------------------------------------------------------------------------------
- }
- }else{ //得到16位计算结果 <<<====(大循环0号,目的)
- break; //跳出
- }
- //-----------------------循环2号,截取前数(可减后数,即必须比后数大)部分-------------------------------------------------------------------------------
- do
- {
- if(shushu1.shujuabc[ic]>shushu2.shujuabc[jc]){ //从高位开始比较
- ic=(mc&0x0f)+shushu2.zscd+shushu2.sscd-1; //前数截取长度和后数等长
- break; //跳出(大的时候会跳出) <<<====(出口1)
- }else{
- if(shushu1.shujuabc[ic]!=shushu2.shujuabc[jc]){ //前数比后数小
- if(shushu1.shujuabc[ic]!=0){ //该位不是0,前数截取长度比后数多1位肯定比后数大
- ic=(mc&0x0f)+shushu2.zscd+shushu2.sscd; //前数截取比后数多1位数
- if(!(gc&0x80)){ //gc最高位是0,在gc最高位是1的情况下nc不能加加
- nc++; //计算结果位置移位
- gc|=0x80; //最高位置1,表示前数截取部分比后数长1位数
- }
- }else{ //该位是0
- if(ic==mc){ //0是前数截取部分第一位
- ic++; //判断位移位
- mc++; //mc低四位加一同步ic
- jc=mc>>4; //后数回到起始位置
- gc&=0x7f; //高位置0,表示
- gc|=0x01; //gc最低位作为这一情况的标志,表示不用运算
- nc++;
- }else{ //0是前数截取部分非首位,首位肯定不是0,这种情况是前数截取部分减了后数若干次后的结果小于后数了
- ic=(mc&0x0f)+shushu2.zscd+shushu2.sscd; //前数截取比后数多1位数
- if(!(gc&0x80)){ //gc最高位是0,在gc最高位是1的情况下nc不能加加,比如,4480-452=4028,4028-452这种情况nc不能加
- nc++; //计算结果位置移位
- gc|=0x80; //最高位置1,表示前数截取部分比后数长1位数
- }
- }
- }
- break; //跳出(小的时候跳出) <<<====(出口2)
- }else{ //前数和后数高位一样大
- if(jc!=shushu2.zscd+shushu2.sscd-1){ //后数数据没有取完,继续下位比较
- ic++;
- jc++;
- }else{ //前数和后数一样大
- ic=(mc&0x0f)+shushu2.zscd+shushu2.sscd-1; //前数截取长度和后数等长
- break; //跳出(相等的时候跳出) <<<====(出口3)
- }
- }
- }
- }while(1);
- //----------------------------------------------------------------------------------------------------------------------------------------------------
- if(!(gc&0x01)){ //gc最低位是1的时候,不进行运算
- jc=shushu2.zscd+shushu2.sscd-1; //后数尾数开始运算
- //------------------------------------循环3号,前数截取部分-后数,求得可减次数,化除法为减法----------------------------------------------
- do
- {
- if(shushu1.shujuabc[ic]>=shushu2.shujuabc[jc]){ //前数不比后数小
- shushu1.shujuabc[ic]-=shushu2.shujuabc[jc]; //前数-后数
- if(jc==mc>>4){ //后数取完了
- if(ic!=(mc&0x0f)){ //前数截取部分没取完
- if(shushu1.shujuabc[ic-1]==0){ //前数多的一位是0
- gc&=0x7f; //最高位置0,表示如果减后的前数截取部分长度比后数小的话,存储位置nc需要加加
- }else{ //这里说明肯定比后数还大,存储位置nc不能移位
- ic--;
- }
- }
- break; //跳出循环 <<<====(循环3号,出口)
- }else{
- ic--;
- jc--;
- }
- }else{ //前数比后数小
- //----------------------------------只进行数据改变,不运算-----------------------------------------------------------
- shushu1.shujuabc[ic]+=10; //加10
- if(shushu1.shujuabc[ic-1]!=0){ //当前运算前数的前一位不等于0
- shushu1.shujuabc[ic-1]--; //减一位
- }else{ //当前运算前数的前一位等于0
- //-----------------------------循环4号,寻找可借位高位-----------------------------------------------------------
- gc|=ic; //gc这里的作用是保存当前ic的值,ic最大值13,用gc的低四位足够
- ic--;
- do
- {
- shushu1.shujuabc[ic]=9; //0位置9
- if(shushu1.shujuabc[ic-1]!=0){ //找可以减的位 <<<====(循环4号,目的)
- shushu1.shujuabc[ic-1]--; //减一
- break; //跳出
- }else{ //再找
- ic--;
- }
- }while(1);
- ic=gc&0x7f; //ic恢复原保存值
- gc&=0x80; //保留最高位,清除其他位
- //--------------------------------------------------------------------------------------------------------------
- }
- //-----------------------------------------------------------------------------------------------------------------
- }
- }while(1);
- //------------------------------------------------------------------------------------------------------------------------------------
- jshcq[nc]++; //前数截取部分和后数减一次,计算结果累加一次
- }
- gc&=0x80; //最高位不变,其他位清零
- }while(1);
- //-------------------------------------------------------------------------------------------------------------------------
- Lcd_qinpin(); //LCD显示数组清零,准备存储计算结果
- jc=0;
- gc=0;
- //-------------------计算结果和显示转换--------------------------
- if(xc<16){
- //-----计算结果大于等于1(还有0.几的情况在内)-----------------
- nc=16-xc;
- //-------------------计算结果数据处理--------------------------
- if(jshcq[0]==0&&nc!=1){ //计算结果首位数字是0,并且不是0.
- jc++; //起始数据位置加一
- nc--; //小数点位置同步
- }
- //-------------------存入显示数组------------------------------
- for(ic=0;ic<16;ic++){ //计算结果转换为显示数据
- if(ic==nc){ //小数点位置
- lcdxs[ic]='.';
- }else{ //数字位置
- lcdxs[ic]=jshcq[jc]+0x30;
- jc++;
- }
- }
- //---------删除计算结果后面无效的0----------------------------
- ic=15;
- do
- {
- if(lcdxs[ic]=='0'||lcdxs[ic]=='.'){ //这里存在一种情况,如果一个计算结果是无理数并且显示尾部是0,那么0也会被不显示,这虽然不是想要的结果,但还可以接受
- lcdxs[ic]=' ';
- ic--;
- }else{
- break;
- }
- }while(1);
- //---------------------------------------------------------------
- }else{
- //-------------------计算结果小于1-------------------------------------------
- nc=xc-14;
- //------------计算结果小于等于0.001采用科学计数法----------------------------
- if((nc==4&&jshcq[0]==0)||nc>4){
- if(jshcq[0]!=0){ //没算小数点的计算结果首位不是0,nc要减一
- nc--;
- }else{ //首位0不用显示
- jc++;
- }
- //-------------------固定显示部分------------------------------------------
- lcdxs[1]='.';
- if(nc<10){
- lcdxs[13]='e';
- lcdxs[14]='-';
- lcdxs[15]=nc+0x30;
- mc=12; //下面删除无效0不显示有用
- }else{
- lcdxs[12]='e';
- lcdxs[13]='-';
- lcdxs[14]=nc/10+0x30;
- lcdxs[15]=nc%10+0x30;
- mc=11; //下面删除无效0不显示有用
- }
- //-------------------存入显示数组------------------------------------------
- for(ic=0;ic<14;ic++){ //计算结果转换为显示数据
- if(lcdxs[ic]==' '){ //lcdxs[]没有赋值
- lcdxs[ic]=jshcq[jc]+0x30;
- jc++;
- if(lcdxs[ic]!='0'){ //lcdxs[]只要有一位数不是0,gc就赋值1
- gc=1;
- }
- }
- }
- //-----------------------特殊情况------------------------------------------
- if(gc==0){ //全是0,表示计算结果无效
- Lcd_qinpin();
- lcdxs[0]='x'; //显示x,表示计算不出来,当计算结果小于1/9999999999999时
- }else{
- do
- {
- if(lcdxs[mc]=='0'||lcdxs[mc]=='.'){ //这里存在一种情况,如果一个计算结果是无理数并且显示尾部是0,那么0也会被不显示,这虽然不是想要的结果,但还可以接受,比如,计算结果9.99000999000e-4会显示9.99000999e-4
- lcdxs[mc]=' ';
- mc--;
- }else{
- break;
- }
- }while(1);
- }
- //----------------------------------------------------------------------------
- }else{
- //------------计算结果大于0.001-----------------------------------------
- for(ic=0;ic<16;ic++){ //0和小数点部分
- if(ic<nc){
- if(ic==1){
- lcdxs[ic]='.';
- }else{
- lcdxs[ic]='0';
- }
- }else{ //其余部分
- lcdxs[ic]=jshcq[jc]+0x30;
- jc++;
- }
- }
- ic=15;
- do
- {
- if(lcdxs[ic]=='0'||lcdxs[ic]=='.'){ //这里存在一种情况,如果一个计算结果是无理数并且显示尾部是0,那么0也会被不显示,这虽然不是想要的结果,但还可以接受
- lcdxs[ic]=' ';
- ic--;
- }else{
- break;
- }
- }while(1);
- }
- //-------------------------------------------------------------------------
- }
- //----------------------------------------------------------------------------
- return 0xff;
- }
- /*************************************************************************************************
- *功能:四则运算
- *************************************************************************************************/
- void Jisuan(void)
- {
- u8 yun,u=0;
- yun=Yunsf_Jl();
- switch(yun)
- {
- case '+':
- yun=Jiafa(); //yun的作用变了
- break;
- case '-':
- yun=Jianfa();
- break;
- case '*':
- yun=Chengfa();
- break;
- case '/':
- yun=Chufa();
- break;
- default:
- break;
- }
- if(yun!=0xff){ //排除除法,其他3种算法需执行的程序
- Lcd_qinpin(); //LCD显示数组清零,准备存储计算结果
- do
- {
- lcdxs[u]=jshcq[yun%16]+0x30; //计算结果存储数组中的数据以字符形式放入LCD显示数组
- if(yun%16!=0){
- if(u==yun/16){ //小数位处理
- u++;
- lcdxs[u]='.';
- }
- yun--; //jshcq[]存放形式低位到高位
- u++; //lcdxs[]存放形式高位到低位
- }else{ //跳出循坏条件:数据取完
- break;
- }
- }while(1);
- //--------------去掉计算结果后面没用的0---------------------------比如,34.00
- if(yun/16!=15){ //有小数点时
- do
- {
- if(lcdxs[u]=='0'){ //碰到'0'
- lcdxs[u]=' '; //空格符代替
- }else{
- if(lcdxs[u]=='.'){ //碰到'.'
- lcdxs[u]=' '; //空格符代替
- }
- break; //碰到非'0'数字字符跳出
- }
- u--; //移位,判断下一位
- }while(1);
- }
- //-----------去掉计算结果前面没用的0------------------------------比如,00.34
- u=0;
- do
- {
- if(lcdxs[u]=='0'){
- if(lcdxs[u+1]=='.'){
- break; //当计算结果是'0''.'的时候,跳出循环
- }else{
- if(lcdxs[u+1]==' '){ //计算结果是'0'的时候
- break;
- }
- lcdxs[u]=' '; //如果'0'后面没跟'.'
- u++; //移位,准备下一位判断
- }
- }else{
- if(lcdxs[u]!='-'){
- break; //碰到不是'-',跳出循环
- }else{
- u++;
- }
- }
- }while(1);
- }
- }
复制代码 |