您的位置:首页 > 其它

分数的四则运算

2015-11-19 19:14 901 查看
如果k属于集合Q,Q={ p/q | p是整数,q是正整数,p与q互质},那么k是有理数,Q是有理数集。

也就是说,有理数都能表示成分数的形式,下面用分数的四则运算来实现有理数的四则运算。

首先记几个单词: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: