分数的四则运算
2015-11-19 19:14
901 查看
如果k属于集合Q,Q={ p/q | p是整数,q是正整数,p与q互质},那么k是有理数,Q是有理数集。
也就是说,有理数都能表示成分数的形式,下面用分数的四则运算来实现有理数的四则运算。
首先记几个单词:fraction 分数,denominator 分母,numerator 分子,sign 符号
下面会用到求最大公约数函数gcd,查看定义请戳这里
也会用到可变参数函数,如果不清楚,请戳这里
首先定义分数结构以及一些需要的宏
两个分数相加,返回和
两个分数相减,返回差
两个分数相乘,返回积
两个分数相除,返回商
求倒数
分数的n次幂,n是整数,返回其n次幂
读入分数,n为要读入分数的个数,...的使用方法和scanf类似,函数返回输入分数的个数
输出分数,方法和printf类似,用%r输入分数,返回输出分数的个数
下面是测试程序
也就是说,有理数都能表示成分数的形式,下面用分数的四则运算来实现有理数的四则运算。
首先记几个单词:fraction 分数,denominator 分母,numerator 分子,sign 符号
下面会用到求最大公约数函数gcd,查看定义请戳这里
也会用到可变参数函数,如果不清楚,请戳这里
首先定义分数结构以及一些需要的宏
#define abs(a) ((a)>=0?(a):-(a))//绝对值 #define swap(a,b,type) do{ type t;t=a;a=b;b=t; }while(0)//交换变量 #define sgn(a) ((a)>0?1:((a)<0?-1:0))//符号函数 typedef long DataType; typedef struct { DataType nume;//分子为整数 DataType deno;//分母为正整数 }Frc;
两个分数相加,返回和
Frc frc_add(Frc *opd1,Frc *opd2) { Frc frc; DataType t; assert(opd1&&opd2); //判断其中的一个分数是否为0 if(0==opd1->nume) return *opd2; if(0==opd2->nume) return *opd1; if(opd1->deno==opd2->deno)//如果分母相等 { frc.nume=opd1->nume+opd2->nume; frc.deno=opd1->deno; } else//如过分母不同 { frc.nume=opd1->nume*opd2->deno+opd1->deno*opd2->nume; frc.deno=opd1->deno*opd2->deno; } if(0==frc.nume)//如果结果为0 return frc; //约分 t=gcd(abs(frc.nume),frc.deno); if(1==t) return frc; frc.nume/=t; frc.deno/=t; return frc; }
两个分数相减,返回差
Frc frc_sub(Frc *opd1,Frc *opd2) { Frc t; assert(opd1&&opd2); t=*opd2; t.nume=-t.nume; return frc_add(opd1,&t); }
两个分数相乘,返回积
Frc frc_mul(Frc *opd1,Frc *opd2) { Frc frc={0,1};//规定了分母不能为0 DataType t; assert(opd1&&opd2); if(0==opd1->nume||0==opd2->nume)//如果其中一个分数为0 return frc; frc.nume=opd1->nume*opd2->nume; frc.deno=opd1->deno*opd2->deno; t=gcd(abs(frc.nume),frc.deno);//约分 if(1==t) return frc; frc.nume/=t; frc.deno/=t; return frc; }
两个分数相除,返回商
Frc frc_div(Frc *opd1,Frc *opd2) { Frc frc={0,1};//分母规定不能为0 int sign; assert(opd1&&opd2); if(0==opd2->nume)//如果除数为0 exit(1); if(0==opd1->nume)//如果被除数为0 return frc; sign=sgn(opd2->nume);//保存opd2符号 frc=*opd2; swap(frc.nume,frc.deno,int); frc.deno=abs(frc.deno);//保证分母为正 frc.nume*=sign; return frc_mul(opd1,&frc); }
求倒数
Frc frc_inverse(Frc *opd) { Frc frc; int sign; assert(opd); if(0==opd->nume)//分子为0,没有倒数 exit(1); sign=sgn(opd->nume);//保存符号 frc.nume=opd->deno*sign; frc.deno=abs(opd->nume); return frc; }
分数的n次幂,n是整数,返回其n次幂
Frc frc_pow(Frc *opd,int n) { int t=n; int sign; Frc frc={0,1}; assert(opd); if(n==0) return frc; if(0==opd->nume) if(n>0) return frc; else//0没有负数次方 exit(1); frc=*opd; if(n<0)//如果是负次方 frc=frc_inverse(opd); if(1!=opd->nume)//分子n次方 while(--t) frc.nume*=opd->nume; if(1!=opd->deno)//分母n次方 while(--n) frc.deno*=opd->deno; return frc; }
读入分数,n为要读入分数的个数,...的使用方法和scanf类似,函数返回输入分数的个数
int frc_input(int n,...) { int cnt=0; Frc *frc; va_list parg; DataType t; va_start(parg,n); while(n--) { frc=va_arg(parg,Frc*); scanf("%d",&frc->nume); if(getchar()=='/')//判断是否需要输入分母 scanf("%d",&frc->deno); else frc->deno=1; if(frc->deno==0)//如果分母为0 return 0; if(frc->deno<0)//如果分母为负 { frc->nume=-frc->nume; frc->deno=abs(frc->deno); } t=gcd(abs(frc->nume),frc->deno);//约分 if(1!=t) { frc->nume/=t; frc->deno/=t; } cnt++; }va_end(parg); return cnt; }
输出分数,方法和printf类似,用%r输入分数,返回输出分数的个数
int frc_print(char *format,...) { int cnt=0;//记录输出了几个分数 Frc frc; va_list parg; assert(format); va_start(parg,format); while(*format) { switch(*format) { case '%': if('%'==*(format+1))//如果是%%,则输出% { putchar('%'); format++; } else if('r'==*(format+1)) { frc=va_arg(parg,Frc); printf("%d",frc.nume); if(1!=frc.deno)//判断是否需要输出分母 printf("/%d",frc.deno); cnt++; format++; } else putchar(*format); break; default: putchar(*format); break; } format++; }va_end(parg); return cnt; }
下面是测试程序
#include<stdio.h> #include<stdarg.h> #include<assert.h> #include<stdlib.h> int main(int argc,char *argv[]) { int instr; Frc frc1,frc2; head(); while(1) { printf("\ninstruction:"); scanf("%d",&instr); switch(instr) { case 0://退出 goto end_pro;case 1://输入 frc_input(2,&frc1,&frc2); break; case 2://输出 frc_print("frc1 = %r frc2 = %r",frc1,frc2); break; case 3://加 frc_print("%r + %r = %r",frc1,frc2,frc_add(&frc1,&frc2)); break; case 4://减 frc_print("%r - %r = %r",frc1,frc2,frc_sub(&frc1,&frc2)); break; case 5://乘 frc_print("%r * %r = %r",frc1,frc2,frc_mul(&frc1,&frc2)); break; case 6://除 frc_print("%r / %r = %r",frc1,frc2,frc_div(&frc1,&frc2)); break; case 7://倒数 frc_print("inverse %r = %r",frc1,frc_inverse(&frc1)); break; case 8://3次幂 frc_print("(%r)^3=%r",frc1,frc_pow(&frc1,3)); break; case 9: head(); break; default: break; } } end_pro: return 0; }
相关文章推荐
- 一个用于灰度标定的matlab函数
- PAT(Basic)-1006.换个格式输出整数(15)
- OpenGL DC RC关系
- MongoDBm基本概念的分析
- ELK安装配置
- dijkstra 昂贵的聘礼 poj1062
- svn使用简介
- ios枷锁解锁
- PHP5踩坑记
- JMS总结
- 如何写css
- metasploit篇-03
- Android Studio1.4.x JNI开发基础-基本环境配置
- C++:位操作基础篇之位操作全面总结
- [ASP.NET 5]终于解决:Unable to load DLL 'api-ms-win-core-localization-obsolete-l1-2-0.dll'
- 数据结构与基本运算
- java题目-1:输入20个学生的成绩,算出算出平均分和低于平均分的人数
- Sphinx相关资料
- asp.net Forms 身份验证 html页面
- Android中ListView分类