-
2021-05-20 07:42:16
资源描述:
单片机C语言快速精度除法方案
目前的51单片机在进行带小数点结果的除法一般可以采用浮点数计算的方式,但是浮点数计算有一个缺点就是非常耗时,在对时间要求严格的工况就不太适用。
笔者最近做了个单片机计算器的项目,在设计除法时利用长整形除法和取余运算,可以得到若干小数位的精度运算,与大家共享。
设计思路如下:
假设长整形除数a, 长整形被数b,步骤如下:
<1>得到除法的整数部分,c=a/b;
<2>设d为a%b,e=10*d,
得到除法的第一位小数,f=e/b;
(要点:将a余b的余数乘以10倍,再和被除数b相除,就得到小数点后一位小数)
<3>设g为e%b,h=10*g,
得到除法的第二位小数,i=h/b;
以此类推,可以得到除法的任意小数……
/***********下面附上C语言程序,永珂科技工作室-提供单片机、电路板、机电液、工控、控制器、自动化、软件等解决方案。QQ
**********************************************************/
unsigned long result, result_p;//表示除法结果的整数和小数部分
// result_p是小数部分,例如result_p=,表示0.
Void chufa(unsigned long chushu, unsigned long beichushu, unsigned char wei)
// wei表示精确到小数点后多少位
{ unsigned char i;
unsigned long tmp;
result=result_p=0;
if (beichushu!=0)//被除数必须不为0
{
if (wei==0)
{result=chushu/beichushu;//计算整数部分
result_p=0;
}
else
{result=chushu/beichushu;//计算整数部分
tmp=chushu%beichushu;
for (i=1;i<=wei;i++)//计算小数部分
{tmp=tmp*10;
result_p=result_p*10+tmp/beichushu;
tmp=tmp%beichushu;
}
}
}
}
更多相关内容 -
C语言整数乘除法练习器
2021-03-12 12:06:42C语言整数乘除法练习器 任务描述:编写一个整数乘除法练习器,提供给小学生使用。可进行100以内任意两个整数的乘除法练习。 功能要求:(1)随机生成乘法或除法运算符。 (2)随机生成100以内的两个正整数。 (3)...C语言整数乘除法练习器
任务描述:编写一个整数乘除法练习器,提供给小学生使用。可进行100以内任意两个整数的乘除法练习。
功能要求:(1)随机生成乘法或除法运算符。
(2)随机生成100以内的两个正整数。
(3)乘法的计算结果不得大于100,否则重新生成题目
(4)除法的计算结果必须为整数,否则重新生成题目。
(5)每次练习开始前,由用户指定要做的题目数量(<=100)。根据题目随机满足上述要求的试题。
(6)对用户输入的答案,判断正确与否,并计分。答对一题得10分。
(7)练习结束后,统计并输出回答正确和错误的题目数,最后得分,并给出相应评语。#include<stdio.h> #include<stdlib.h> #include<time.h> #include<Windows.h> void goto_xy(int x, int y); void show1(); int getchoice(); int dowork(int n); int num(); void print(int s,int n); void goto_xy(int x, int y) //定位光标位置到指定坐标 { HANDLE hOut; hOut = GetStdHandle(STD_OUTPUT_HANDLE); COORD pos = { x,y }; SetConsoleCursorPosition(hOut, pos); } void show1() //开始界面 { printf("****************************************\n"); printf("| |\n"); printf("| |\n"); printf("| |\n"); printf("| |\n"); printf("| 欢迎使用整数乘除法练习器 |\n"); printf("| |\n"); printf("| 1. 开始 |\n"); printf("| 2. 退出 |\n"); printf("| |\n"); printf("| 请选择: |\n"); printf("| |\n"); printf("| |\n"); printf("| |\n"); printf("****************************************\n"); } int getchoice() { int a; goto_xy(16,10); scanf("%d",&a); return a; } int num() //题量获取 { int n; printf("请输入要做的题目数:\n"); goto_xy(19,0); scanf("%d",&n); return n; } int dowork(int n) //练习模块 { int a,b,c,d,e,i,s=0,x=0,y=0; srand((int)time(NULL)); for(i=0;i<n;i++) { e=rand()%2; a=rand()%100; b=rand()%100; if(e==0) //乘法 { if(a*b<100) { printf("%d*%d=\n",a,b); scanf("%d",&d); if(a*b==d) { printf("正确!\n"); s+=10; x++; } else { printf("错误!\n"); y++; } } else { n++; continue; } } if(e==1) //除法 { if(b!=0&&a%b==0) //b不能为零,无意义 { printf("%d/%d=\n",a,b); scanf("%d",&c); if(a/b==c) { printf("正确!\n"); s+=10; x++; } else { printf("错误!\n"); y++; } } else { n++; continue; } } } printf("您一共做了%d道题,其中正确%d道,错误%d道\n",x+y,x,y); return s; } void print(int s,int n) //根据百分比输出结果及评语 { printf("您的得分是:%d\n",s); if(s/10/n<0.6) printf("成绩不及格.\n请努力!\n"); if(s/10/n>=0.6&&s/10/n<0.8) printf("成绩及格.\n请加油!"); if(s/10/n>=0.8) printf("成绩优秀.\n再接再厉!\n"); } int main() { int a,n1,n2,s; system("mode con cols=40 lines=17"); //控制输出界面大小 system("color E4"); //字体颜色与背景 L: show1(); a=getchoice(); if(a==1) { system("cls"); //清屏代码 n1=n2=num(); printf("Let's go!!!\n"); } else if(a==2) { system("cls"); printf("谢谢使用!\n"); return 0; } s=dowork(n1); print(s,n2); Sleep(4000); //延迟4秒 goto L; //跳转到 L 标签 }
-
恢复余数法定点原码一位除法器的设计
2011-01-03 22:22:20定点原码一位除法器的原理是根据人工进行二进制除法的规则:判断被除数与除数的大小,若被除数小,则上商0,并在余数最低位补0,再用余数和右移一位的除数比,若够除,则上商1,否则上商0。然后继续重复上述步骤,... -
基于FPGA的除法器设计
2019-07-15 16:50:52所以有必要来设计一款除法器,使其不占用那么多逻辑资源,并且所用时钟数能够满足约束要求。(减弱空间复杂度、增加时间复杂度,并且满足时间约束)。 计算机内部乘除法原理 众所周知,计算机所能完成的基本元操作...用FPGA写代码时候,尽量不用“/”,因为其占用大量逻辑资源。所以有必要来设计一款除法器,使其不占用那么多逻辑资源,并且所用时钟数能够满足约束要求。(减弱空间复杂度、增加时间复杂度,并且满足时间约束)。
计算机内部乘除法原理
众所周知,计算机所能完成的基本元操作是:+(-),左移,右移等指令。
乘法实现
计算机中用二进制进行计数,例如8(D) = 1000(B)。任何一个数均可以表示为下式:
所以数a乘以X,就变成了下式子:
此即计算机乘法原理对计算机而言,
左移1位代表乘以2,
右移1位代表除以2。
所以,对于a乘以x而言,只是将a左移x为1的位并累加即可。举例说明:5*3=5 *(2+1)
1. 3=0011(不用分解,计算机就是这么存储的);
2. 3的第0位1,5左移0位仍为5;
3. 3的第一位为1,5左移1位为5 * 2 = 10;
4. 然后将其累加,得到最后结果15。除法实现
传统的十进制除法计算
当我们在计算51/3=17,抛开9*9乘法表。
1. 从被除数的最高位5开始,从0-9选一个数,使得5-i*3>=0且使5-(i+1)3<0。我们选择了1,余数为2;
2. 将余数 * 10+1=21,继续从0-9中选一个数,使得21-3i>=0且使21-(i+1)*3<0,我们选择了7;
3. 由此,我们找到了答案17。计算机除法计算
计算机计算除法的过程与人类计算的过程很类似,只是选择范围变成了0或1。
还以51/3为例说明(51:110011;3:11)1. 从第一位开始,为1,小于11,结果位置0,余数为1;
2. 从第二位开始,余数2+1=11,等于11,结果位置1,余数为0;
3. 从第三、四位开始,余数2+0=0<011,结果位置0,余数为0;
4. 从第5位开始,余数2+1=1<11,结果置0,余数为1;
5. 从第6位开始,余数2+1=11=11,结果置1,余数为0。
把结果位相连恰好是010001(17)。
以上所介绍的乘除法原理都有对应的C语言代码参考>https://blog.csdn.net/zdavb/article/details/47108505,前面介绍只是参考扩充而已,我们主要是用Verilog HDL写代码,慢慢往下文看。计算机补码
正数的补码是其本身,负数的补码是符号位不变,除此之外的位取反加一;
计算机中补码运算时,符号位都是参与运算的。
比如1_110(-2)+0_101(+5)=0_101(+3);
补码的补码就是原码。
加法运算:
[x+y]补=[x]补+[y]补
可直接相加。
减法运算:
[x-y]补=[x]补+(-[y]补)
x的补码加上y补码的相反数。(符号也要相反)(称为机器负数)。计算机里,加法与减法是统一的,能够形成统一是由于补码。须知道,俩个正整数相减,可以看成是一个正整数加一个负整数,进一步,俩个正整数相减是用一个正整数的补码加上一个负整数的补码来得到的。
在这里,我主要想介绍的是补码运算时的溢出判断溢出判断
俩个相同位数的二进制补码相加,得到的正确结果位数与俩加数相同,并且符号位准确。
这里的溢出不是指
二进制无符号数据位相加,然后最高位有溢出则称作溢出的。(FPGA里对有符号的数是怎么运算的?要好好了解一下。)首先,一个正数和一个负数相加,结果一定不会溢出(因为结果的绝对值一定小于两个加数的绝对值,两个加数都表达出来了,结果定能表达出来)。 所以,溢出只能是符号相同的俩数相加。 正+正: 符号位0,数位相加,如果结果的符号位变成1了,那一定是两个加数的最高位相加进上来的。 发生溢出。 负+负: 符号位都是1,所以符号位一定会进位。数位相加,如果最后符号位是0,说明结果变成正的了,那一定是发生溢出了(负+负!=正)。 大家会困惑“为何负数补码最高位相加,发生进位的不是溢出,反而不进位是溢出呢?”在补码发生溢出的情况中,在补码发生溢出的情况中, 正数是因为太大发生溢出; 但是负数是因为它太小发生的溢出。 有进位说明两个负数较大。(数据位未进位到符号位,符号位自己发生进位溢出了) 大家想,负数比较小,那么他们的补码肯定是比较大的,那数据位相加会有进位可能,而符号位已经都为1了, 那么1+1=0,然后再加上数据位进位的1,所以符号位最后得出的结果还是负数。 当负数比较大的时候,他们的补码比较小,数据位是没有溢出給符号位,可是因为符号位是全1,所以符号位会溢出, 那么最后得到的结果只有扩大一位位宽,用来存放溢出位并作为新的符号位才对。 比如1_001(-7)+1_100(-4)=1_0101(-11)。
双符号位判断溢出:
原来符号位只有一个,现在为了方便再加一个。
正数:00 负数 11
结果01时,结果为正,发生正溢出(正数太大了)
结果10时,结果为负,发生负溢出(负数太小了)
还是00或11就是没有溢出了。
有人会问,难道负溢出就不会是11了吗?
举例:我们想让结果进位到符号位,又要让加数最小(绝对值最大,这样才能溢出)
11100是最好的用例(这是发生进位的最小补码)。
我们把两个 11100 相加
11100+11100=111000 -> 11000 这时发生溢出了吗?
11000是-8,加数 11100是-4。移位运算:
算数移位:在二进制中,算数移位的左移 每移一位表示*2,右移表示/2 ; 原码移位,符号位不参与移位; 补码移位,符号位参与移位。左移时符号位左移,右移时符号位不变,最高位补符号位; 逻辑移位:把数字看成一串二进制数,让怎么移就怎么移,符号位和数位没区别。
正整数型移位除法器
假设被除数与除数都是八位数据,这里的算法是:
将被除数,扩展成16位的数据,低8位为被除数的值,高八位的初始值全为0。有开始信号,对16位数据data赋值,然后开始运算。比较data的高八位和除数的值,如果大于0,说明被除数大,将此时商置1,赋值给data的最低位,然后将被除数高八位减去除数。然后将data向左移位一位,继续比较。最终计算8次后。Data的高8位数据就为所求的余数,低八位就为所求的商。
原理说白了就是:先移位,在比较(作差),迭代八次。
下面就是写Verilog Code了,我所用的FPGA型号是ALTERA公司的EP4CE30F23C8N。/* / module fifo #(parameter MSB=3, LSB=0, DEPTH=4)//可以被重写 (port_list ); item; endmodule 在上层模块对参数重写的方式如下:F1.MSB=4;F1.LSB=2;fifo F1; / module fifo (port_list ); parameter MSB=3, LSB=0, DEPTH=4//可以被重写 endmodule 在上层模块对参数重写方式如下:fifo #(4,2) F1(port_list); / module fifo #(parameter MSB=3, LSB=0)//可以被重写 (port_list ); parameter DEPTH=4; //不能被重写 endmodule 在上层模块对参数重写方式如下:fifo #(.LSB(2), .MSB(4)) fifo(port_list); */ module DIV_INT_TYPE # ( parameter E = 16, //Extension of bits parameter D = 8 //The bits of dividend and divisor )( input clk,//50MHz input rst_n, input start, //除法开始的使能标志 output reg busy, //start开启后,busy=1代表除法器在忙,除法器被占用。当除法器忙的时候,start就要为0; input [D-1:0] dividend, //[ˈdɪvɪdend] 被除数 input [D-1:0] divisor, // [dɪˈvaɪzər] 除数 output wire [D-1:0] quotient, // [ˈkwoʊʃnt] 商 output wire [D-1:0] remainder, // [rɪˈmeɪndər] 余数 output reg finish //除法完成 ); / ///以下是一段式状态机来写的整数除法器内核 reg [1:0] state;//状态机 reg [D-1:0] count; reg [E-1:0] data_next; always @ ( posedge clk or negedge rst_n )begin if( !rst_n )begin count <= D; state <= 2'd0; end else begin case( state ) 2'd0:begin finish <= 1'b0; busy <= 1'b0; if( start == 1'b1 )begin data_next <= {{E-D{1'b0}},dividend}; state <= 2'd1; end else begin data_next <= 0; state <= 2'd0; end end 2'd1:begin if( data_next[E-1:D] >= divisor )begin//如果余数大于等于除数 //data_next[0] = 1'b1; //data_next[E-1:D] = data_next[E-1:D] - divisor; //如果余数大于除数,那就对data_next做相应运算,可是我们接着要对运算完的data_next进行移位操作,这样才不会吃时钟,所以把这两步操作合为一体91行即是 if( count == 0 )begin state <= 2'd0; finish <= 1'b1; busy <= 1'b0; data_next <= data_next; count <= D; end else begin state <= state; finish <= 1'b0; busy <= 1'b1; data_next[E-1:0] <= {{data_next[E-1:D] - divisor},data_next[D-1:1],1'b1} << 1'b1; count <= count - 1'b1; end end else begin if( count == 0 )begin state <= 2'd0; finish <= 1'b1; busy <= 1'b0; data_next <= data_next; count <= D; end else begin state <= state; finish <= 1'b0; busy <= 1'b1; data_next <= data_next << 1'b1; count <= count - 1'b1; end end end default:begin count <= D; state <= 2'd0; end endcase end end assign quotient = finish?data_next[D-1:0] : quotient; assign remainder = finish?data_next[E-1:D] : remainder; / / ///下面为二段式状态机所写的整数除法器内核 /* parameter idle = 3'b000; parameter shift = 3'b001; parameter done = 3'b010; reg [2:0] state_current; reg [2:0] state_next; reg [E-1:0] data_next; reg [E-1:0] temp; reg [D-1:0] count;//count用来计数移位次数 //俩段式状态机,此模块是时序逻辑进行当前状态和下一状态的切换。。俩段式状态机组合逻辑那块用来实现各个输入输出以及状态判断 always @ ( posedge clk or negedge rst_n )begin if( !rst_n )begin state_current <= idle; count <= D; end else begin state_current <= state_next; if( state_current == shift )begin count <= count-1'b1; end else begin count <= D; end end end /// always @ ( posedge clk )begin//always块有俩种触发方式:1,边沿触发;2,电平触发。在这里是说always块里语句里面所有输入信号只要其中一个发生变化就能触发always块语句 case( state_current ) idle:begin finish = 1'b0; busy = 1'b0; if( start == 1'b1 )begin data_next = {{E-D{1'b0}},dividend};//初始值={0000_0000,dividend};E-D=8,8'{1'b0}={1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0} state_next = shift; end else begin state_next = idle; data_next = 0; end end shift:begin finish = 1'b0; busy = 1'b1; data_next = data_next << 1;//{data_next[E-2:0],1'b0};//移位操作 if( data_next[E-1:D] >= divisor )begin//如果余数大于等于除数 data_next[0] = 1'b1; data_next[E-1:D] = data_next[E-1:D] - divisor; end else begin data_next = data_next; end if( count == 1 )begin state_next = done; end else begin state_next = shift; end end done:begin finish = 1'b1; busy = 1'b0; state_next = idle; end default:begin finish = 1'b0; busy = 1'b0; data_next = 0; end endcase end assign quotient = finish?data_next[D-1:0] : quotient; assign remainder = finish?data_next[E-1:D] : remainder; */ endmodule
module CTRL_DIV # ( parameter D = 8 ) ( input clk, input rst_n, input busy, input finish, output reg start, output reg [D-1:0] dividend, output reg [D-1:0] divisor ); reg [1:0] i; always @ ( posedge clk or negedge rst_n )begin if( !rst_n )begin i <= 2'd0; start <= 1'b0; dividend <= { D{1'b0} }; divisor <= { D{1'b0} }; end else begin case( i ) 2'd0: if( busy == 1'b0 )begin i <= i+1'b1; divisor <= {{ D-1{1'B0} },1'B1};//1 dividend <= {{ D-1{1'B1} },1'B0};//254 start <= 1'b1; end else begin i <= i; divisor <= divisor; dividend <= dividend; start <= 1'b0; end 2'd1: if( finish )begin dividend <= dividend; if( divisor == {{ D-1{1'B1} },1'B0} )begin divisor <= divisor; start <= 1'b0; i <= 2'd0; end else begin divisor <= divisor + 1'b1; start <= 1'b1; i <= i; end end else begin dividend <= dividend; divisor <= divisor; start <= 1'b0; i <= i; end default:begin i <= 2'd0; start <= 1'b0; dividend <= { D{1'b0} }; divisor <= { D{1'b0} }; end endcase end end endmodule
module TOP #( parameter D = 8 ) ( input clk, input rst_n, output [D-1:0] quotient, // [ˈkwoʊʃnt] 商 output [D-1:0] remainder, // [rɪˈmeɪndər] 余数 output wire finish //除法完成 ); wire busy; DIV_INT_TYPE #(.E( 16 ),.D( 8 )) DIV_INT_TYPE( .clk( clk ), .rst_n( rst_n ), .start( start ), .busy( busy ), .dividend( dividend ), .divisor( divisor ), .quotient( quotient ), .remainder( remainder ), .finish( finish ) ); wire start; wire [D-1:0] dividend; wire [D-1:0] divisor; CTRL_DIV # ( .D( 8 ))( .clk( clk ), .rst_n( rst_n ), .busy( busy ), .finish( finish ), .start( start ), .dividend( dividend ), .divisor( divisor ) ); endmodule
Signal Tap II仿真波形见下图:
被除数是8位固定值254,除数是在一次除法完成后就进行累加。经测试,除法器所用时钟为固定不变的11个clk,时钟频率是50MHz。
上面的代码中俩段式状态机代码是错误的,不要看。吃时钟的整数型除法器设计
介绍此吃时钟除法器设计是为下面“整数型除法器设计”作铺垫的。后面的设计是根据此设计来的。注意,在FPGA里,对于一个IP核若输出或输出有负数,都是用补码形式进行的。所以要对补码的运算有了解,一个正数的补码加一个负数的补码不会溢出。
此设计只止于思维上的分析了,用C语言也完全可以写出来,在时钟消耗方面没有下功夫,未得FPGA精髓。
代码算法理念:
1. 先取除数和被除数的正负关系,然后正值化被除数。除数取负值的补码;
2. 被除数递减与除数,每一次的递减,商数递增;
3. 直到被除数小于除数,递减过程剩下的都是余数;
4. 输出的结果根据除数和被除数的正负关系来划分。module DIVIDER_SIGN_INT//八位带符号除法器内核 ( input clk, //50MHz时钟 input rst_n, //全局复位信号 input start, //除法器使能信号,为“1”时,除法器状态机才能执行 input [7:0] dividend, //被除数 input [7:0] divisor, //除数 output done, //一次除法完成 output [7:0] quotient, //商 output [7:0] reminder //余数 ); reg [3:0] i; //状态机 reg [7:0] dend; //寄存器,对被除数取正,即存取被除数绝对值的补码 reg [7:0] dsor_n; //寄存器,对除数取负,即存取( -|除数| )补码 reg [7:0] dsor_p; //寄存器,对除数取正,即存取除数绝对值的补码 reg [7:0] q; //寄存器,商。用于always块 reg dif; //商正负符号判别标志 reg done_sig; always @ ( posedge clk or negedge rst_n )begin if( !rst_n )begin i <= 4'd0; dend <= 8'd0; dsor_n <= 8'd0; dsor_p <= 8'd0; q <= 8'd0; dif <= 1'b0; done_sig <= 1'b0; end else if( start )begin case( i ) 4'd0:begin dend <= dividend[7] ? ~dividend + 1'b1 : dividend;//被除数取正 dsor_n <= divisor[7] ? divisor : (~divisor + 1'b1);//除数取负 dif <= dividend[7] ^ divisor[7];//正负判断,之前错误写的是dif <= dividend ^ divisor; q <= 8'd0;//商初值化 i <= i+1'b1;//进入下一状态机 end 4'd1:begin if( dsor_p > dend )begin//正除数与每一步的正余数比较,当正除数大于( |被除数|-N*|除数| )时,除法器就可以输出最终值了。算法中思想是,被除数是由几个除数组成。 q <= dif ? (~q + 1'b1) : q;//输出余数补码形式,除法过程本身q是以正数补码叠加的;所以当被除数与除数异号时,q要以对应的负数补码形式输出。 i <= i+1'b1;//一次除法完成,进入下一状态机。 end else begin dend <= dend + dsor;//dend在除法动作过程中,肯定是越来越小,因为一个正数和负数的和还是正数,且和小于前面的正加数。 q <= q+1'b1;//每进行一次叠加,就表示对被除数的一次细分 i <= i;//对被除数进行细分,多次细分未完成,状态机不变,只有当dsor_p > dend时,细分才结束,状态机才跳转 end end 4'd2:begin done_sig <= 1'b1;//一次除法已经完成标志,除法完成标志是一个周期的正脉冲 i <= i+1'b1; end 4'd3:begin done_sig <= 1'b0; i <= 4'd0; end default:begin i <= 4'd0; dend <= 8'd0; dsor <= 8'd0; q <= 8'd0; dif <= 1'b0; done_sig <= 1'b0; end endcase assign done = done_sig; assign quotient = q; assign reminder = dend; endmodule
下面是Signal Tap II仿真波形
仿真结果很直观暴露了该除法器的弱点,即不同的除数,就有不一样的时钟消耗。时钟消耗是根据除数的“数量”来做决定。
整数型除法器设计
在设计中,补码运算采用了双符号来进行对被除数与除数绝对值的比较。正数的补码与负数的补码进行相加,正数补码的符号位就是“00”,负数补码的符号位是“11”,符号位左边为高位,右边为低位。通过对正负数补码相加后得到的值的高位符号位进行判别二者模的大小。如果高位为“1”,则代表负数模大,反之则代表正数模大。此算法与楼上“正整数型除法器设计”的算法思路是一致的,只不过楼上是正整数除法,而这里是整数除法。仿真读者可以自行用Modelsim来写Test Bench模块验证一下,个人建议有板子的话用Quartus自带的Signal Tap II验证更为准确。
module DIV_SIGN_INT( input clk, //50MHz时钟 input rst_n, //全局复位 input start, //除法器使能信号 input [7:0] dividend; //被除数 input [7:0] divisor, //除数 output finish, //一次除法完成标志 output [7:0] quotient, //商 output [7:0] reminder //余数 ); reg [3:0] i; //状态机 reg [8:0] dsor; //双符号位11_| divisor[6:0] |补码 reg [15:0] temp; //除法器移位比较运算的扩展空间,temp = 0000 00_00 |dividend|补码 reg [15:0] dif_compare; //此空间是用于 |被除数|补码 左移后 与 (-|除数|)补码的比较,注意都是双符号位,当dif[15]为1则代表负数(负除数双符号位的补码表示)大,反之代表正数(指双符号位被除数正值化)大。 reg dif; //被除数与除同号与否的判断 reg finish_sig; //一次除法完成的标志位,完成后输出一个时钟正脉冲 always @ ( posedge clk or negedge rst_n )begin if( !rst_n )begin i <= 4'd0; dsor <= 9'd0; temp <= 16'd0; dif_compare <= 16'd0; dif <= 1'b0; finish_sig <= 1'b0; end else if( start )begin case( i ) 0:begin dif <= dividend[7] ^ divisor[7];//判断二者符号同异 dsor <= divisor[7] ? { 1'b1,divisor } : { 1'b1,~divisor+1'b1 };//除数取负化,且采用双符号位表示 temp <= dividend[7] ? { 8'd0,~dividend+1'b1 } : { 8'd0,dividend };//被除数取正化放于低八位 dif_compare <= 16'd0; i <= i+1'b1; end 1,2,3,4,5,6,7,8:begin dif_compare = temp + { dsor,7'd0 }; if( dif_compare[15] )begin //如果除数绝对值大,temp继续左移,低位补零 temp <= { temp[14:0],1'b0 }; else begin //如果被除数大于除数绝对值,左移,并且低位补1,最后移位8次后,低位为商,高位为余数 temp <= { dif_compare[14:0],1'b1 }; end i <= i+1'b1; end 9:begin finish_sig <= 1'b1; i <= i+1'b1; end 10:begin finish_sig <= 1'b0; i <= 2'd0; end endcase end end assign finish = finish_sig; assign quotient = dif ? ( ~temp[7:0]+1'b1 ) : temp[7:0]; assign reminder = temp[15:8]; endmodule
-
c语言实现科学计算器(除法运算取整),同时拥有算术练习功能
2022-02-03 21:16:33目录 1. calculate.h头文件定义 2. 编写main.c源文件,选择计算器模式还是算术练习模式 3. 在calculator.c源文件中编写科学计算器的相关函数 3.1 创建数据栈和符号栈,存储算式中数据和符号 ...目录
2. 编写main.c源文件,选择计算器模式还是算术练习模式
3. 在calculator.c源文件中编写科学计算器的相关函数
3.2 初始化数据栈和符号栈头指针下标为 -1 ,即data.top = -1和symbol.top = -1
3.3 先简单编写void calculator()函数,开辟字符串空间将输入的算式存入字符串str中
3.4 在calculator()函数中编写循环,将str字符串中数据和符号存入数据栈和符号栈
4.2 编写中阶乘除法练习medium()函数,涉及浮点数,需要将结果保留两位小数与输入数进行比较
4.3 编写高阶综合练习的high()函数, 注意一个地方不涉及除法不用四舍五入
先上效果图:
思路:
1.创建calculate.h头文件,进行函数声明;
2.创建calculator.c源文件,编写科学计算器函数calculator();
3.创建exercise.c源文件,编写算术练习函数exercise();
4.创建main.c源文件,运行主函数。
步骤:
1. calculate.h头文件定义
#include <stdio.h> #include <stdlib.h> //清屏 #include <time.h> //随机数、计时 void calculator(); //计算器计算 void exercise(); //算术练习
2. 编写main.c源文件,选择计算器模式还是算术练习模式
#include "calculate.h" void menu() { printf("************************************\n"); printf("***********1.计算器 **************\n"); printf("***********2.算数练习 **************\n"); printf("***********0.退出 **************\n"); printf("************************************\n"); printf("请选择:>"); } int main() { int input; do { menu(); scanf("%d", &input); system("cls"); //清屏,提高观感 switch (input) { case 1: calculator(); //计算器函数 break; case 2: exercise(); //计算练习函数 break; case 0: printf("退出程序\n"); break; default: printf("输入错误,请重新输入\n"); break; } } while (input); return 0; }
3. 在calculator.c源文件中编写科学计算器的相关函数
3.1 创建数据栈和符号栈,存储算式中数据和符号
struct shujv { int data[100]; int top; }; struct fuhao { char symbol[100]; int top; };
3.2 初始化数据栈和符号栈头指针下标为 -1 ,即data.top = -1和symbol.top = -1
void InitNum(struct shujv* Num) { Num->top = -1; } void InitSymbol(struct fuhao* Symbol) { Symbol->top = -1; }
3.3 先简单编写void calculator()函数,开辟字符串空间将输入的算式存入字符串str中
void calculator() { struct shujv data; struct fuhao symbol; //创建数据栈、符号栈 InitNum(&data); InitSymbol(&symbol); //初始化数据栈、符号栈 int i, j; i = j = 0; int v1, v2, ret; //用于计算的变量 char c; char v[100]; printf(" 计算器\n"); printf("************************************\n"); printf("请输入算式: "); char* str = (char*)malloc(sizeof(char) * 200); //开辟空间存放输入的算式 getchar(); //吸收上一次选择时的'\n' while ((c = getchar()) != '\n') { str[i] = c; i++; } str[i] = '\0'; //下面则编写进行计算的循环,将算式中的数据和符号分别存入不同栈 }
3.4 在calculator()函数中编写循环,将str字符串中数据和符号存入数据栈和符号栈
3.4.1 创建字符串数字v[100], 若str[i]为数字,则进行循环将连续的数字存入字符串v中,再将字符串v利用函数atio(v)转换为数字存入数据栈data.data
3.4.2 若str[i]为字符,则进行优先级判断( str[i] 就是 str[symbol.tol] ) ,在决定存入符号栈symbol.symbol或者让前面的数据进行运算;
- 若symbol.top = -1 且为 - ,则是表示负号的符号,直接存入符号栈,再进行数据的存储;
- 若symbol.top = -1 ,说明符号栈为空,直接将 str[i] 存入;
- 若str[i]为 ( , ( 优先级为最高,直接存入符号栈;
- 若str[i]为 + 或者 - ,对栈顶符号( str[symbol.top] )进行读取判断。若栈顶符号为 ( ,直接存入;若栈顶符号为 + 或 - ,则进行出栈循环(让前两个数据进行运算,将栈顶符号消耗掉),再将str[i]存入;若栈顶符号为 * 或 / ,同样是出栈循环,再将str[i]存入;
- 若str[i]为 * 或者 / ,一样对栈顶符号进行读取判断。若栈顶符号为 ( ,直接存入;若栈顶符号为 + 或 - ,由于乘除的优先级更高,所以str[i]直接存入;若栈顶符号为 * 或 / ,出栈循环,再将str[i]存入;
- 若str[i]为 ) ,则出栈循环运算直到遇到 ( ,再将 ( 处理掉,str[i]不存入数据栈
3.4.3 当扫描字符串str的循环结束后,再进行一次出栈循环直到symbol[symbol.top] = -1 , 此时data.data[0] 就是我们需要的计算结果。
for (i = 0; str[i] != '\0'; i++) { if (i == 0 && str[i] == '-') { v[j++] = str[i]; } else if (str[i] == '(' && str[i + 1] == '-') { i++; v[j++] = str[i++]; while (str[i] >= '0' && str[i] <= '9') { v[j] = str[i]; j++; i++; } Inshujv(&data, atoi(v)); //将数据存入数据栈,atoi()可将字符串转换为int型整数 while (j > 0) //data.top++ { v[j] = 0; j--; } if (str[i] != ')') { i--; Infuhao(&symbol, '('); //将符号存入符号栈,symbol.top++ } } else if (str[i] >= '0' && str[i] <= '9') { while (str[i] >= '0' && str[i] <= '9') { v[j] = str[i]; j++; i++; } Inshujv(&data, atoi(v)); while (j > 0) { v[j] = 0; j--; } i--; } else { if (symbol.top == -1) //如果符号栈还没有元素,则直接将符号存入 { Infuhao(&symbol, str[i]); } else if (str[i] == '(') //如果是优先级最高的'('也直接存入符号栈 { Infuhao(&symbol, str[i]); } else if (str[i] == '+' || str[i] == '-') //此时根据栈顶符号判断优先级 { if (Readfuhao(&symbol) == '(') //如果栈顶为'('则直接存入 { Infuhao(&symbol, str[i]); } else if (Readfuhao(&symbol) == '+' || Readfuhao(&symbol) == '-') //如果栈顶为加减做出栈运算 { while (symbol.top >= 0 && data.top >= 1 && symbol.symbol[symbol.top] != '(') { v2 = Putshujv(&data); v1 = Putshujv(&data); ret = Math(v1, v2, Putfuhao(&symbol)); Inshujv(&data, ret); } Infuhao(&symbol, str[i]); } else if (Readfuhao(&symbol) == '*' || Readfuhao(&symbol) == '/') { while (symbol.top >= 0 && data.top >= 1 && symbol.symbol[symbol.top] != '(') { v2 = Putshujv(&data); v1 = Putshujv(&data); ret = Math(v1, v2, Putfuhao(&symbol)); Inshujv(&data, ret); } Infuhao(&symbol, str[i]); } } else if (str[i] == '*' || str[i] == '/') { if (Readfuhao(&symbol) == '(') { Infuhao(&symbol, str[i]); } else if (Readfuhao(&symbol) == '+' || Readfuhao(&symbol) == '-') { Infuhao(&symbol, str[i]); } else if (Readfuhao(&symbol) == '*' || Readfuhao(&symbol) == '/') { while (symbol.top >= 0 && data.top >= 1 && symbol.symbol[symbol.top] != '(' && symbol.symbol[symbol.top] != '+' && symbol.symbol[symbol.top] != '-') { v2 = Putshujv(&data); v1 = Putshujv(&data); ret = Math(v1, v2, Putfuhao(&symbol)); Inshujv(&data, ret); } Infuhao(&symbol, str[i]); } } else if (str[i] == ')') //若为')'则做出站运算知道遇到'(' { do { v2 = Putshujv(&data); v1 = Putshujv(&data); ret = Math(v1, v2, Putfuhao(&symbol)); Inshujv(&data, ret); } while (symbol.symbol[symbol.top] != '('); Putfuhao(&symbol); //处理掉'(' } } } while (symbol.top >= 0 && data.top >= 1) { v2 = Putshujv(&data); v1 = Putshujv(&data); ret = Math(v1, v2, Putfuhao(&symbol)); Inshujv(&data, ret); } system("cls"); printf(" 计算器\n"); printf("************************************\n"); printf("%s = %d\n\n",str, data.data[0]); free(str);
3.5 编写数据和符号存入栈的函数
//存入数据栈 void Inshujv(struct shujv* Num, int n) { Num->top++; Num->data[Num->top] = n; } //存入符号栈 void Infuhao(struct fuhao* Symbol, char ch) { Symbol->top++; Symbol->symbol[Symbol->top] = ch; }
3.6 编写读取栈顶符号的函数
//读取栈顶符号 char Readfuhao(struct fuhao* Symbol) { return Symbol->symbol[Symbol->top]; }
3.7 编写输出数据和符号的函数
//输出数据 int Putshujv(struct shujv* Num) { int x; x = Num->data[Num->top]; Num->top--; return x; } //输出符号 char Putfuhao(struct fuhao* Symbol) { char ch; ch = Symbol->symbol[Symbol->top]; Symbol->top--; return ch; }
3.8 编写四则运算的函数
//四则运算 int Math(int a, int b, char ch) { if (ch == '+') return a + b; if (ch == '-') return a - b; if (ch == '*') return a * b; if (ch == '/') return a / b; }
4.在exercise.c源文件中编写算术练习的相关函数
4.1 编写void exercise()函数
#include "calculate.h" void e_menu() { printf("*****************************\n"); printf("******** 1.初阶练习 *******\n"); printf("******** 2.中阶练习 *******\n"); printf("******** 3.高阶练习 *******\n"); printf("******** 0.退出练习 *******\n"); printf("*****************************\n"); } void exercise() { srand((unsigned int)time(NULL)); int n; do { e_menu(); printf("请选择:>"); scanf("%d", &n); system("cls"); switch (n) { case 1: primary(); //初阶练习,加减法 break; case 2: medium(); //中阶练习,乘除法 break; case 3: high(); //高阶练习,综合训练 break; case 0: printf("退出练习\n"); break; default: printf("输入错误,请重新输入\n"); break; } } while (n); }
4.2 编写初阶加减法练习primary() 函数
void primary() { clock_t start, finish, total; //计算答题时间 int min, sec, ms; int i, n; int count = 0; //记录答错次数 printf(" 初阶练习\n"); printf("---------------------------------\n"); printf("输入你想要挑战的题目数量:"); scanf("%d", &n); start = clock(); for (i = 0; i < n; i++) { int a = rand() % 100; int b = rand() % 100; int c = rand() % 100; if (i % 2 == 0) { printf("\n第 %d 题:%d + %d - %d = ?\n", i + 1, a, b, c); printf("请输入答案:"); int s; scanf("%d", &s); while (s != (a + b - c)) { printf("\n答案错误\n请重新输入:"); count++; scanf("%d", &s); } printf("\n恭喜你,回答正确!\n"); } else { printf("\n第 %d 题:%d - %d + %d = ?\n",i + 1, a, b, c); printf("请输入答案:"); int s; scanf("%d", &s); while (s != (a - b + c)) { printf("\n答案错误\n请重新输入:"); count++; scanf("%d", &s); } printf("\n恭喜你,回答正确!\n"); } } finish = clock(); total = (double)(finish - start) / CLOCKS_PER_SEC; //单位换算为秒 min = (int)total / 60; sec = (int)total % 60; ms = (int)(finish - start) - 60000 * min - 1000 * sec; printf("\n答错次数:%d", count); printf("\n本次挑战 %d 道题目,共用时 %d 分 %d 秒 %d 毫秒\n\n", n, min, sec, ms); }
4.2 编写中阶乘除法练习medium()函数,涉及浮点数,需要将结果保留两位小数与输入数进行比较
void medium() { clock_t start, finish, total; int min, sec, ms; int i, n; int count = 0; printf(" 中阶练习\n"); printf("---------------------------------\n"); printf("输入你想要挑战的题目数量:"); scanf("%d", &n); start = clock(); for (i = 0; i < n; i++) { float a = rand() % 100; float b = rand() % 100; float c = rand() % 10 + 1; float ret = 0; float temp = 0; if (i % 2 == 0) { printf("\n第 %d 题:%.1f * %.1f / %.1f = ?\n", i + 1, a, b, c); ret = a * b / c; temp = (int)(ret * 100 + 0.5); temp = temp / 100; printf("请输入答案(保留两位小数):"); float s; scanf("%f", &s); while (s != temp) { printf("\n答案错误\n请重新输入:"); count++; scanf("%f", &s); } printf("\n恭喜你,回答正确!\n"); } else { printf("\n第 %d 题:%.1f / %.1f * %.1f = ?\n", i + 1, a, c, b); ret = a / c * b; temp = (int)(ret * 100 + 0.5); temp = temp / 100; //将结果四舍五入保留两位小数赋值给temp printf("请输入答案(保留两位小数):"); float s; scanf("%f", &s); while (s != temp) { printf("\n答案错误\n请重新输入:"); count++; scanf("%f", &s); } printf("\n恭喜你,回答正确!\n"); } } finish = clock(); total = (int)(finish - start) / CLOCKS_PER_SEC; //单位换算为秒 min = (int)total / 60; sec = (int)total % 60; ms = (int)(finish - start) - 60000 * min - 1000 * sec; printf("\n答错次数:%d", count); printf("\n本次挑战 %d 道题目,共用时 %d 分 %d 秒 %d 毫秒\n\n", n, min, sec, ms); }
4.3 编写高阶综合练习的high()函数, 注意一个地方不涉及除法不用四舍五入
void high() { clock_t start, finish, total; int min, sec, ms; int i, n; int count = 0; printf(" 高阶练习\n"); printf("---------------------------------\n"); printf("输入你想要挑战的题目数量:"); scanf("%d", &n); start = clock(); for (i = 0; i < n; i++) { float a = rand() % 100; float b = rand() % 100; float c = rand() % 100; float d = rand() % 10 + 1; //加一防止被除数出现小数 float ret = 0; float temp = 0; if (i % 5 == 0) { printf("\n第 %d 题:%.1f + %.1f * %.1f / %.1f = ?\n", i + 1, a, b, c, d); ret = a + b * c / d; temp = (int)(ret * 100 + 0.5); temp = temp / 100; printf("%.2f\n", temp); printf("请输入答案(保留两位小数):"); float s; scanf("%f", &s); while (s != temp) { printf("\n答案错误\n请重新输入:"); count++; scanf("%f", &s); } printf("\n恭喜你,回答正确!\n"); } else if (i % 3 == 0) { printf("\n第 %d 题:%.1f * %.1f / %.1f - %.1f = ?\n", i + 1, a, b, d, c); ret = a * b / d - c; temp = (int)(ret * 100 + 0.5); temp = temp / 100; printf("%.2f\n", temp); printf("请输入答案(保留两位小数):"); float s; scanf("%f", &s); while (s != temp) { printf("\n答案错误\n请重新输入:"); count++; scanf("%f", &s); } printf("\n恭喜你,回答正确!\n"); } else if (i % 2 == 0) { printf("\n第 %d 题:%.1f * %.1f + %.1f / %.1f = ?\n", i + 1, a, b, c, d); ret = a * b + c / d; temp = (int)(ret * 100 + 0.5); temp = temp / 100; printf("%.2f\n", temp); printf("请输入答案(保留两位小数):"); float s; scanf("%f", &s); while (s != temp) { printf("\n答案错误\n请重新输入:"); count++; scanf("%f", &s); } printf("\n恭喜你,回答正确!\n"); } else { printf("\n第 %d 题:%.1f + %.1f - %.1f * %.1f = ?\n", i + 1, a, b, c, d); ret = a + b - c * d; printf("%.2f\n", ret); printf("请输入答案(保留两位小数):"); float s; scanf("%f", &s); while (s != ret) { printf("\n答案错误\n请重新输入:"); count++; scanf("%f", &s); } printf("\n恭喜你,回答正确!\n"); } } finish = clock(); total = (int)(finish - start) / CLOCKS_PER_SEC; //单位换算为秒 min = (int)total / 60; sec = (int)total % 60; ms = (int)(finish - start) - 60000 * min - 1000 * sec; printf("\n答错次数:%d", count); printf("\n本次挑战 %d 道题目,共用时 %d 分 %d 秒 %d 毫秒\n\n", n, min, sec, ms); }
5. 完整函数
5.1 calculate.h头文件
#include <stdio.h> #include <stdlib.h> #include <time.h> void calculator(); //计算器计算 void exercise(); //口算练习
5.2 calculator.c源文件
#include "calculate.h" //数据栈 struct shujv { int data[100]; int top; }; //符号栈 struct fuhao { char symbol[100]; int top; }; void InitNum(struct shujv* Num) { Num->top = -1; } void InitSymbol(struct fuhao* Symbol) { Symbol->top = -1; } //存入数据栈 void Inshujv(struct shujv* Num, int n) { Num->top++; Num->data[Num->top] = n; } //存入符号栈 void Infuhao(struct fuhao* Symbol, char ch) { Symbol->top++; Symbol->symbol[Symbol->top] = ch; } //读取栈顶符号 char Readfuhao(struct fuhao* Symbol) { return Symbol->symbol[Symbol->top]; } //输出数据 int Putshujv(struct shujv* Num) { int x; x = Num->data[Num->top]; Num->top--; return x; } //输出符号 char Putfuhao(struct fuhao* Symbol) { char ch; ch = Symbol->symbol[Symbol->top]; Symbol->top--; return ch; } //四则运算 int Math(int a, int b, char ch) { if (ch == '+') return a + b; if (ch == '-') return a - b; if (ch == '*') return a * b; if (ch == '/') return a / b; } void calculator() { struct shujv data; struct fuhao symbol; //创建数据栈、符号栈 InitNum(&data); InitSymbol(&symbol); //初始化数据栈、符号栈 int i, j; i = j = 0; int v1, v2, ret; //用于计算的变量 char c; char v[100]; printf(" 计算器\n"); printf("************************************\n"); printf("请输入算式: "); char* str = (char*)malloc(sizeof(char) * 200); //开辟空间存放输入的算式 getchar(); //吸收上一次选择时的'\n' while ((c = getchar()) != '\n') { str[i] = c; i++; } str[i] = '\0'; for (i = 0; str[i] != '\0'; i++) { if (i == 0 && str[i] == '-') { v[j++] = str[i]; } else if (str[i] == '(' && str[i + 1] == '-') { i++; v[j++] = str[i++]; while (str[i] >= '0' && str[i] <= '9') { v[j] = str[i]; j++; i++; } Inshujv(&data, atoi(v)); //将数据存入数据栈,atoi()可将字符串转换为int型整数 while (j > 0) { v[j] = 0; j--; } if (str[i] != ')') { i--; Infuhao(&symbol, '('); } } else if (str[i] >= '0' && str[i] <= '9') { while (str[i] >= '0' && str[i] <= '9') { v[j] = str[i]; j++; i++; } Inshujv(&data, atoi(v)); while (j > 0) { v[j] = 0; j--; } i--; } else { if (symbol.top == -1) //如果符号栈还没有元素,则直接将符号存入 { Infuhao(&symbol, str[i]); } else if (str[i] == '(') //如果是优先级最高的'('也直接存入符号栈 { Infuhao(&symbol, str[i]); } else if (str[i] == '+' || str[i] == '-') //此时根据栈顶符号判断优先级 { if (Readfuhao(&symbol) == '(') //如果栈顶为'('则直接存入 { Infuhao(&symbol, str[i]); } else if (Readfuhao(&symbol) == '+' || Readfuhao(&symbol) == '-') //如果栈顶为加减做出栈运算 { while (symbol.top >= 0 && data.top >= 1 && symbol.symbol[symbol.top] != '(') { v2 = Putshujv(&data); v1 = Putshujv(&data); ret = Math(v1, v2, Putfuhao(&symbol)); Inshujv(&data, ret); } Infuhao(&symbol, str[i]); } else if (Readfuhao(&symbol) == '*' || Readfuhao(&symbol) == '/') { while (symbol.top >= 0 && data.top >= 1 && symbol.symbol[symbol.top] != '(') { v2 = Putshujv(&data); v1 = Putshujv(&data); ret = Math(v1, v2, Putfuhao(&symbol)); Inshujv(&data, ret); } Infuhao(&symbol, str[i]); } } else if (str[i] == '*' || str[i] == '/') { if (Readfuhao(&symbol) == '(') { Infuhao(&symbol, str[i]); } else if (Readfuhao(&symbol) == '+' || Readfuhao(&symbol) == '-') { Infuhao(&symbol, str[i]); } else if (Readfuhao(&symbol) == '*' || Readfuhao(&symbol) == '/') { while (symbol.top >= 0 && data.top >= 1 && symbol.symbol[symbol.top] != '(' && symbol.symbol[symbol.top] != '+' && symbol.symbol[symbol.top] != '-') { v2 = Putshujv(&data); v1 = Putshujv(&data); ret = Math(v1, v2, Putfuhao(&symbol)); Inshujv(&data, ret); } Infuhao(&symbol, str[i]); } } else if (str[i] == ')') //若为')'则做出站运算知道遇到'(' { do { v2 = Putshujv(&data); v1 = Putshujv(&data); ret = Math(v1, v2, Putfuhao(&symbol)); Inshujv(&data, ret); } while (symbol.symbol[symbol.top] != '('); Putfuhao(&symbol); //处理掉'(' } } } while (symbol.top >= 0 && data.top >= 1) { v2 = Putshujv(&data); v1 = Putshujv(&data); ret = Math(v1, v2, Putfuhao(&symbol)); Inshujv(&data, ret); } system("cls"); printf(" 计算器\n"); printf("************************************\n"); printf("%s = %d\n\n",str, data.data[0]); free(str); }
5.3 exercise.c源文件
#include "calculate.h" void e_menu() { printf("*****************************\n"); printf("******** 1.初阶练习 *******\n"); printf("******** 2.中阶练习 *******\n"); printf("******** 3.高阶练习 *******\n"); printf("******** 0.退出练习 *******\n"); printf("*****************************\n"); } void primary() { clock_t start, finish, total; //记录答题时间 int min, sec, ms; int i, n; int count = 0; //记录答错次数 printf(" 初阶练习\n"); printf("---------------------------------\n"); printf("输入你想要挑战的题目数量:"); scanf("%d", &n); start = clock(); for (i = 0; i < n; i++) { int a = rand() % 100; int b = rand() % 100; int c = rand() % 100; if (i % 2 == 0) { printf("\n第 %d 题:%d + %d - %d = ?\n", i + 1, a, b, c); printf("请输入答案:"); int s; scanf("%d", &s); while (s != (a + b - c)) { printf("\n答案错误\n请重新输入:"); count++; scanf("%d", &s); } printf("\n恭喜你,回答正确!\n"); } else { printf("\n第 %d 题:%d - %d + %d = ?\n",i + 1, a, b, c); printf("请输入答案:"); int s; scanf("%d", &s); while (s != (a - b + c)) { printf("\n答案错误\n请重新输入:"); count++; scanf("%d", &s); } printf("\n恭喜你,回答正确!\n"); } } finish = clock(); total = (double)(finish - start) / CLOCKS_PER_SEC; //单位换算为秒 min = (int)total / 60; sec = (int)total % 60; ms = (int)(finish - start) - 60000 * min - 1000 * sec; printf("\n答错次数:%d", count); printf("\n本次挑战 %d 道题目,共用时 %d 分 %d 秒 %d 毫秒\n\n", n, min, sec, ms); } void medium() { clock_t start, finish, total; int min, sec, ms; int i, n; int count = 0; printf(" 中阶练习\n"); printf("---------------------------------\n"); printf("输入你想要挑战的题目数量:"); scanf("%d", &n); start = clock(); for (i = 0; i < n; i++) { float a = rand() % 100; float b = rand() % 100; float c = rand() % 10 + 1; float ret = 0; float temp = 0; if (i % 2 == 0) { printf("\n第 %d 题:%.1f * %.1f / %.1f = ?\n", i + 1, a, b, c); ret = a * b / c; temp = (int)(ret * 100 + 0.5); temp = temp / 100; printf("请输入答案(保留两位小数):"); float s; scanf("%f", &s); while (s != temp) { printf("\n答案错误\n请重新输入:"); count++; scanf("%f", &s); } printf("\n恭喜你,回答正确!\n"); } else { printf("\n第 %d 题:%.1f / %.1f * %.1f = ?\n", i + 1, a, c, b); ret = a / c * b; temp = (int)(ret * 100 + 0.5); temp = temp / 100; printf("请输入答案(保留两位小数):"); float s; scanf("%f", &s); while (s != temp) { printf("\n答案错误\n请重新输入:"); count++; scanf("%f", &s); } printf("\n恭喜你,回答正确!\n"); } } finish = clock(); total = (int)(finish - start) / CLOCKS_PER_SEC; //单位换算为秒 min = (int)total / 60; sec = (int)total % 60; ms = (int)(finish - start) - 60000 * min - 1000 * sec; printf("\n答错次数:%d", count); printf("\n本次挑战 %d 道题目,共用时 %d 分 %d 秒 %d 毫秒\n\n", n, min, sec, ms); count = 0; } void high() { clock_t start, finish, total; int min, sec, ms; int i, n; int count = 0; printf(" 高阶练习\n"); printf("---------------------------------\n"); printf("输入你想要挑战的题目数量:"); scanf("%d", &n); start = clock(); for (i = 0; i < n; i++) { float a = rand() % 100; float b = rand() % 100; float c = rand() % 100; float d = rand() % 10 + 1; float ret = 0; float temp = 0; if (i % 5 == 0) { printf("\n第 %d 题:%.1f + %.1f * %.1f / %.1f = ?\n", i + 1, a, b, c, d); ret = a + b * c / d; temp = (int)(ret * 100 + 0.5); temp = temp / 100; printf("%.2f\n", temp); printf("请输入答案(保留两位小数):"); float s; scanf("%f", &s); while (s != temp) { printf("\n答案错误\n请重新输入:"); count++; scanf("%f", &s); } printf("\n恭喜你,回答正确!\n"); } else if (i % 3 == 0) { printf("\n第 %d 题:%.1f * %.1f / %.1f - %.1f = ?\n", i + 1, a, b, d, c); ret = a * b / d - c; temp = (int)(ret * 100 + 0.5); temp = temp / 100; printf("%.2f\n", temp); printf("请输入答案(保留两位小数):"); float s; scanf("%f", &s); while (s != temp) { printf("\n答案错误\n请重新输入:"); count++; scanf("%f", &s); } printf("\n恭喜你,回答正确!\n"); } else if (i % 2 == 0) { printf("\n第 %d 题:%.1f * %.1f + %.1f / %.1f = ?\n", i + 1, a, b, c, d); ret = a * b + c / d; temp = (int)(ret * 100 + 0.5); temp = temp / 100; printf("%.2f\n", temp); printf("请输入答案(保留两位小数):"); float s; scanf("%f", &s); while (s != temp) { printf("\n答案错误\n请重新输入:"); count++; scanf("%f", &s); } printf("\n恭喜你,回答正确!\n"); } else { printf("\n第 %d 题:%.1f + %.1f - %.1f * %.1f = ?\n", i + 1, a, b, c, d); ret = a + b - c * d; printf("%.2f\n", ret); printf("请输入答案(保留两位小数):"); float s; scanf("%f", &s); while (s != ret) { printf("\n答案错误\n请重新输入:"); count++; scanf("%f", &s); } printf("\n恭喜你,回答正确!\n"); } } finish = clock(); total = (int)(finish - start) / CLOCKS_PER_SEC; //单位换算为秒 min = (int)total / 60; sec = (int)total % 60; ms = (int)(finish - start) - 60000 * min - 1000 * sec; printf("\n答错次数:%d", count); printf("\n本次挑战 %d 道题目,共用时 %d 分 %d 秒 %d 毫秒\n\n", n, min, sec, ms); count = 0; } void exercise() { srand((unsigned int)time(NULL)); int n; do { e_menu(); printf("请选择:>"); scanf("%d", &n); system("cls"); switch (n) { case 1: primary(); //初阶练习,加减法 break; case 2: medium(); //中阶练习,乘除法 break; case 3: high(); //高阶练习,综合训练 break; case 0: printf("退出练习\n"); break; default: printf("输入错误,请重新输入\n"); break; } } while (n); }
5.4 main.c源文件
#include "calculate.h" void menu() { printf("************************************\n"); printf("***********1.计算器 **************\n"); printf("***********2.算数练习 **************\n"); printf("***********0.退出 **************\n"); printf("************************************\n"); printf("请选择:>"); } int main() { int input; do { menu(); scanf("%d", &input); system("cls"); //清屏,提高观感 switch (input) { case 1: calculator(); //计算器函数 break; case 2: exercise(); //计算练习函数 break; case 0: printf("退出程序\n"); break; default: printf("输入错误,请重新输入\n"); break; } } while (input); return 0; }
-
程序设计抽象思想:C语言描述.[美]Eric S.Roberts(带详细书签).pdf
2019-03-12 19:32:051.4.3 整数除法和求余运算符 16 1.4.4 类型转换 17 1.4.5 赋值运算符 17 1.4.6 递增与递减运算符 19 1.4.7 布尔运算符 20 1.5 语句 22 1.5.1 简单语句 22 1.5.2 块 22 1.5.3 if语句 23 1.5.4 switch语句 ... -
NUC029LAN代替M0516,硬件除法器,2.5-5.5V,50MHz Cortex-M0,4KB的SRAM,64KB的Flash,4KB的LDOROM-TRM_NUC...
2019-09-03 11:58:14NUC029LAN代替M0516,硬件除法器,2.5-5.5V,50MHz Cortex-M0,4KB的SRAM,64KB的Flash,4KB的LDOROM-TRM_NUC029_Series_EN_Rev1.02.pdf -
c语言程序设计和c程序设计有什么区别啊
2021-05-19 13:58:31C语言是一种计算机程序设计语言。它既有高级语言的特点,又具有汇编语言的特点。它可以作为系统设计语言,编写工作系统应用程序,也可以作为应用程序设计语言,编写不依赖计算机硬件的应用程序。因此,它的应用范围... -
C语言程序设计
2021-10-06 17:55:18C语言程序设计1、C语言基础1.1概述1.2数据类型 1、C语言基础 1.1概述 C是一种通用的计算机程序设计语言,目前用于编写系统软件和嵌入式应用开发。C语言是由系列函数组成,这种结构便于将大型程序分成若干个相对独立... -
FPGA应用笔记——除法器
2020-01-10 22:30:50除法器的设计1.1 需求分析1.2 算法设计1.3 时序设计2. 基于Verilog HDL的实现3. 基于Vivado HLx的仿真结果4. 注意事项 0.除法器简介 FPGA可以实现几乎所有的数字逻辑和时序,FPGA的速度很快,但是如果在用... -
C语言中,求余运算与乘除法运算,哪个的优先级高
2021-05-19 12:28:46C语言中,求余运算与乘除法运算,优先级一样高。C语言是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发。C语言能以简易的方式编译、处理低级存储器。C语言是仅产生少量的机器语言以及不需要任何运行... -
用C语言写一个计算器
2020-12-23 18:03:38用C语言写一个计算器 用C语言写一个计算器,除了四则混合运算之外,还支持三角函数和绝对值等函数。 PS E:\Code\PL\calc> .\a.exe abs(3*5-4^2) abs(3*5-4^2)=1.000000 25-7+6*(4-5) 25-7+6*(4-5)=12.000000 ... -
《C语言程序设计》知识点总结.doc
2021-05-19 20:19:012)读程序都要从main()入口, 然后从最下面顺序往下读(遇到循环做循环,遇到选择做选择)做c语言程序设计的总结,有且只有一个main函数。 3)计算机的数据在手机中留存是以二进制的方式. 数据存放的位置就是它的地址. 4)... -
c语言设计简单计算器实现加减乘除运算
2021-05-21 05:23:17编写程序的目的就是使程序有他应用的地方,编写一个简单的计算器来实现我们计算的目的。利用swich case 语句和循环结构来实现简单程序的编写。利用选择语句来进行输入的选择,然后利用所输入的数字的不同进行不同... -
单片机与DSP中的一种基于AVR单片机的工频干扰滤除快速算法
2020-12-08 13:18:56这种算法从AVR单片机内部硬件乘法器的特点出发,采用分配系统数法进行低通数字滤波器设计。经过VMLAB集成开发环境的仿真验证,算法速度快、代码效率高、滤波效果理想。 关键词:单片机 定点小数 FIR 工频干扰 分配... -
解决ARM7单片机除法运算的新方法
2021-03-23 11:59:01这本文介绍了一种在ARM7处理器上进行除法运算的算法,并给出了相应的子例程,可以直接在汇编程序设计中使用。 该算法是类似于使用减法电路进行除法的数字电路的工作原理手术。 给定的子例程可以处理两个32位无符号... -
两数相加的加法器/减法/除法/乘法
2019-07-05 14:47:53两数相加的加法器/减法/除法/乘法(C语言): 代码: #include <stdio.h> int ppp(int x,int y); //函数的声明 int main() { int a,b,c; scanf("%d%d",&a,&b); c=ppp(a,b); //函数的调用 printf(... -
小学生加减乘除法做题系统,代码为纯c语言
2020-11-12 11:39:36为小学的广大学子写一个,加减乘除法做题系统,思路简单清晰,...2.人性化设计:从分考虑到小学的算法运算将运算的数据,设计为100以内,减法皆为大数减小数,并且乘除法皆为倍数乘除法 3.为提高学习质量,每做完一题 -
编译原理实验二——算符优先分析法设计与实现
2021-08-29 21:43:53用算符优先分析方法设计一个分析解释程序,对输入的赋值语句、输出语句、清除语句进行词法分析、语法分析、表达式求值并存储于指定变量中;若存在错误,提示错误相关信息。 -
《C语言》课程设计——小学生四则运算器
2021-04-01 22:53:41《C语言》课程设计——小学生四则运算器一、问题功能描述二、基本原理三、主要技术问题的描述四、创新要求五、程序代码 一、问题功能描述 编制小学生进行加减乘除四则运算的练习程序。首先进行运算种类和运算数范围... -
C语言程序设计——猜数字游戏
2021-11-24 19:59:13游戏玩法:每次随机生成一个1~100之间的数字,玩家通过输入数字来猜这个数,如果没猜中则提示玩家猜大了或者猜小了,直到玩家猜中数字结束游戏。 游戏玩法非常简单,那么怎么实现呢? 首先对内容进行分析,我们... -
用C语言编写一个简易计算器可实现加减乘除,连加连减,连乖连除.
2021-05-19 13:47:57#include#include"stdlib.h"#defineN10voidfun(){inta,b,t;charc;scanf("%d",&a);scanf("%c",&c);scanf("%d",&b);if(c=='+'||c=='-'||c=='*'||c=='/'||c=='%'){if(c=='+')t=a+b;if(c=='-')t=a-b... -
用C语言写一个简单的加减乘除计算器。
2021-04-21 13:26:58用C语言写一个简单的加减乘除计算器。 #include <stdio.h> #include <stdlib.h> int data1; int data2; void tips() { printf("**************************************************\n"); printf("*... -
C语言程序设计基本步骤
2021-05-20 01:39:09一、Turbo C程序设计基本步骤程序设计方法包括三个基本步骤:第一步: 分析问题。第二步: 画出程序的基本轮廓。第三步: 实现该程序。3a. 编写程序3b. 测试和调试程序3c. 提供数据打印结果下面, 我们来说明每一步的具体... -
C语言例题:设计一个两个整数进行运算的计算器
2019-05-11 15:00:26题目:编写一个程序,实现两个整数可以进行加减乘除的计算器。 #include<stdio.h> int m, n; void add(int m,int n) { printf("计算结果为:%d + %d = %d\n", m, n, m + n); } void subtration(int m,... -
c语言实现加减乘除计算器
2021-11-24 21:15:33#include<stdio.h> #include<stdlib.h> void menu() { printf(" 1.加法 2.减法 \n ");... printf(" 3....除法 \n"); printf(" 0.退出 \n"); } int jia(int x, int y) { return x + y; ... -
C语言程序设计(苏小红,高等教育出版社)学习笔记(一)
2019-07-08 12:41:53C语言程序设计(苏小红,高等教育出版社)学习笔记(一) ##第一章 为什么要学C语言 1.学编程的过程,其实就是学习怎样用编程语言说话,让编译器听懂的过程。 2.汇编语言缺少“可移植性” 除了机器语言和汇编... -
【简单地过一遍C语言基础部分】所有知识点,点到为止!(仅一万多字)
2021-09-13 13:43:45就在前几天,C语言入门到进阶部分的专栏——《维生素C语言》终于完成了。全文共计十八个章节并附带三张笔试练习篇,美中不足的是,第一章和第二章是以截图形式展现的。由于本人一开始是在有道云笔记上写的初稿,当时... -
华为C语言编程规范(精华总结)
2020-03-24 09:48:55则建议每一个子模块提供一个对外的 .h,文件名为子模块名 降低接口使用者的编写难度 14、头文件不要使用非习惯用法的扩展名,如 .inc 目前很多产品中使用了.inc作为头文件扩展名,这不符合c语言的习惯用法。... -
用C语言写一个 小学生口算出题系统
2021-05-19 20:39:25除法 5.结束"); printf("\n"); printf("\n选择难度:"); scanf("%d",&o); switch(o) { case 1:jiafa();break; case 2:jianfa();break; case 3:chengfa();break; case 4:chufa();break; case 5:exit(0);break; ...