zoukankan      html  css  js  c++  java
  • 分数的四则运算

     如果k属于集合Q,Q={ p/q | p是整数,q是正整数,p与q互质},那么k是有理数,Q是有理数集。

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

     首先记几个单词:fraction 分数,denominator 分母,numerator 分子,sign 符号

     下面会用到求最大公约数函数gcd,查看定义请戳这里

     也会用到可变参数函数,如果不清楚,请戳这里

     首先定义分数结构以及一些需要的宏

     1 #define abs(a)         ((a)>=0?(a):-(a))//绝对值
     2 #define swap(a,b,type) do{ type t;t=a;a=b;b=t; }while(0)//交换变量
     3 #define sgn(a)         ((a)>0?1:((a)<0?-1:0))//符号函数
     4 
     5 typedef long DataType;
     6 typedef struct
     7 {
     8     DataType nume;//分子为整数
     9     DataType deno;//分母为正整数
    10 }Frc;

     两个分数相加,返回和

     1 Frc frc_add(Frc *opd1,Frc *opd2)
     2 {
     3     Frc frc;
     4     DataType t;
     5     assert(opd1&&opd2);
     6     //判断其中的一个分数是否为0 
     7     if(0==opd1->nume)
     8         return *opd2;
     9     if(0==opd2->nume)
    10         return *opd1;
    11     if(opd1->deno==opd2->deno)//如果分母相等 
    12     {
    13         frc.nume=opd1->nume+opd2->nume;
    14         frc.deno=opd1->deno;
    15     }
    16     else//如过分母不同
    17     {
    18         frc.nume=opd1->nume*opd2->deno+opd1->deno*opd2->nume;
    19         frc.deno=opd1->deno*opd2->deno;
    20     }
    21     if(0==frc.nume)//如果结果为0 
    22         return frc;
    23     //约分 
    24     t=gcd(abs(frc.nume),frc.deno);
    25     if(1==t)
    26         return frc;
    27     frc.nume/=t;
    28     frc.deno/=t;
    29     return frc;
    30 }

     两个分数相减,返回差

    1 Frc frc_sub(Frc *opd1,Frc *opd2)
    2 {
    3     Frc t;
    4     assert(opd1&&opd2);
    5     
    6     t=*opd2;
    7     t.nume=-t.nume;
    8     return frc_add(opd1,&t);
    9 }

     两个分数相乘,返回积

     1 Frc frc_mul(Frc *opd1,Frc *opd2)
     2 {
     3    Frc frc={0,1};//规定了分母不能为0 
     4    DataType t;
     5    assert(opd1&&opd2);
     6    
     7    if(0==opd1->nume||0==opd2->nume)//如果其中一个分数为0 
     8        return frc;
     9    frc.nume=opd1->nume*opd2->nume;
    10    frc.deno=opd1->deno*opd2->deno;
    11    
    12    t=gcd(abs(frc.nume),frc.deno);//约分 
    13    if(1==t)
    14        return frc;
    15    frc.nume/=t;
    16    frc.deno/=t;
    17    return frc; 
    18 }

     两个分数相除,返回商

     1 Frc frc_div(Frc *opd1,Frc *opd2)
     2 {
     3     Frc frc={0,1};//分母规定不能为0
     4     int sign;
     5     assert(opd1&&opd2);
     6     
     7     if(0==opd2->nume)//如果除数为0 
     8         exit(1);
     9     if(0==opd1->nume)//如果被除数为0 
    10         return frc;
    11         
    12     sign=sgn(opd2->nume);//保存opd2符号 
    13     frc=*opd2;
    14     swap(frc.nume,frc.deno,int);
    15     frc.deno=abs(frc.deno);//保证分母为正 
    16     frc.nume*=sign;
    17     return frc_mul(opd1,&frc);
    18 }

    求倒数

    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次幂

     1 Frc frc_pow(Frc *opd,int n)
     2 {
     3     int t=n;
     4     int sign;
     5     Frc frc={0,1};
     6     assert(opd);
     7     
     8     if(n==0)
     9         return frc;
    10     if(0==opd->nume)
    11         if(n>0)
    12             return frc;
    13         else//0没有负数次方 
    14             exit(1);
    15     frc=*opd;
    16     if(n<0)//如果是负次方 
    17         frc=frc_inverse(opd);
    18     if(1!=opd->nume)//分子n次方 
    19         while(--t)
    20             frc.nume*=opd->nume;
    21     if(1!=opd->deno)//分母n次方 
    22         while(--n)
    23             frc.deno*=opd->deno;
    24     return frc;
    25 }

    读入分数,n为要读入分数的个数,...的使用方法和scanf类似,函数返回输入分数的个数

     1 int frc_input(int n,...)
     2 {
     3     int cnt=0;
     4     Frc *frc;
     5     va_list parg;
     6     DataType t;
     7     
     8     va_start(parg,n);
     9     while(n--)
    10     {
    11         frc=va_arg(parg,Frc*);
    12         scanf("%d",&frc->nume); 
    13         if(getchar()=='/')//判断是否需要输入分母 
    14             scanf("%d",&frc->deno);
    15         else
    16             frc->deno=1;
    17         if(frc->deno==0)//如果分母为0 
    18             return 0;
    19         if(frc->deno<0)//如果分母为负 
    20         {
    21             frc->nume=-frc->nume;
    22             frc->deno=abs(frc->deno);
    23         }
    24         t=gcd(abs(frc->nume),frc->deno);//约分 
    25         if(1!=t)
    26         {
    27             frc->nume/=t;
    28             frc->deno/=t;
    29         }
    30         cnt++;
    31     }va_end(parg);
    32     return cnt;
    33 }

    输出分数,方法和printf类似,用%r输入分数,返回输出分数的个数

     1 int frc_print(char *format,...)
     2 {
     3     int cnt=0;//记录输出了几个分数
     4     Frc frc;
     5     va_list parg;
     6     assert(format);
     7     
     8     va_start(parg,format);
     9     while(*format)
    10     {
    11         switch(*format)
    12         {
    13             case '%':
    14                 if('%'==*(format+1))//如果是%%,则输出% 
    15                 {
    16                     putchar('%');
    17                     format++;
    18                 }
    19                 else if('r'==*(format+1))
    20                 {
    21                     frc=va_arg(parg,Frc);
    22                     printf("%d",frc.nume);
    23                     if(1!=frc.deno)//判断是否需要输出分母 
    24                         printf("/%d",frc.deno);
    25                     cnt++;
    26                     format++;
    27                 }
    28                 else
    29                     putchar(*format);
    30                 break;
    31             default:
    32                 putchar(*format);
    33                 break;
    34         }
    35         format++;
    36     }va_end(parg);
    37     return cnt;
    38 }

    下面是测试程序

    #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("
    instruction:");
            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;
    }
  • 相关阅读:
    函数
    向discuz里填充数据
    CI 基础
    FlashBuilder设置显示字符集
    win2003 Email邮件服务器搭配
    CI 模块化显示[仿照shopex功能]
    DW的鸟语
    CI 视图里加视图
    silverlight模拟单击事件
    自定义XML配置文件的操作类(转)
  • 原文地址:https://www.cnblogs.com/inori/p/4975897.html
Copyright © 2011-2022 走看看