分数的四则运算

如果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("\ninstruction:");
        scanf("%d",&instr);
        switch(instr)
        {
            case 0://退出
                break;
            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;
        }
    }

    return 0;
}
时间: 2024-08-05 02:40:46

分数的四则运算的相关文章

数学问题——分数的四则运算

所谓分数的四则运算是指,给定两个分数的分子和分母,求它们加减乘除的结果. 一. 分数的表示和化简 1. 分数的表示 对一个分数来说,最简洁的写法就是写成 假分数 的形式.因此可以使用一个结构体来储存这种只有分子和分母的分数: 1 // 分数的表示 2 typedef struct { 3 int up, down; // 分子,分母 4 } Fraction; 于是就可以定义 Fraction 类型的变量来表示分数,或者定义数组来表示一堆分数.其中需要对这种表示制定三项规则: 使 down 为非

c++重载运算符实验定义分数类实现分数间四则运算

实验二           自定义类型的运算 [实验目的] 理解运算符函数与运算符重载方法: 掌握运算符重载为友元函数: [实验内容] 题目: 在C++中,分数不是预先定义的,建立一个分数类,使之具有以下功能:能防止分母为0.当分数不是最简形式时进行约分及分母为负数.用重载运算符完成加法.减法.乘法.除法等四则运算. 源程序代码: #include<iostream> #include<cstdlib> using namespace std; int gcd(int m,int

写一个能自动生成四则运算题目的软件,要求除了整数,还要支持正分数的四则运算。和同学们比较各自的程序功能、实现方法的异同。

package Rational; import java.util.Random; import java.util.Scanner; public class szys{             public static void res() {                                                   System.out.println("1.显示答案\t2.直接出下一题");                             

对随机产生分数或整数的四则运算的代码实现

一设计思想: 一.完成如何实现随机调取两个数和一个四则运算符号 二.如何实现以四则运算题的形式输出 三.如何实现选择性输出多少题 四.如何补加输出分数的功能 二.代码实现 package com.minirisoft; import java.util.*; public class Yunsuan { public static void main(String[] args){ Scanner input=new Scanner(System.in); System.out.println(

对随机产生分数或整数的四则运算题的代码实现

一设计思想: 一.完成如何实现随机调取两个数和一个四则运算符号 二.如何实现以四则运算题的形式输出 三.如何实现选择性输出多少题 四.如何补加输出分数的功能 二.代码实现 package com.minirisoft; import java.util.*; public class Yunsuan { public static void main(String[] args){ Scanner input=new Scanner(System.in); System.out.println(

个人作业1——四则运算题目生成程序(基于控制台)

No.1 四则运算题目生成程序(基于控制台) 程序代码 需求分析: 能够根据用户自身对题目数量的需求自动生成一定数量的包含分数的四则运算题目的命令行程序. 功能设计: 除了整数以外,还要支持真分数的四则运算,真分数的运算 并且要求能处理用户的输入,并判断对错,打分统计正确率 要求能处理用户输入的真分数 使用 -n 参数控制生成题目的个数 设计实现: 程序是用c++实现的,主要有四个函数,主函数随机生成整数或者分数算法,divisor(int i, int j)计算最大公约数,zs为计算整数算法,

四则运算多功能版

功能一:支持正负数的四则运算,排除(1/3这类情况) 功能展示如下 功能:二:支持带括号的四则运算: 功能展示如下: 功能三:支持括号运算,并且打印结果. 功能展示如下: 功能四:支持分数的四则运算. 功能展示如下: 总结:看似容易的事,实现起来总是会出现很多问题,要考虑很多要出现的边界情况.此次的作业虽然基本完成,但是自己知道其实还是有bug.(ps:不想掩饰缺点) 代码地址:  https://coding.net/u/muziliquan/p/classwork02/git/tree/ma

自动生成四则运算题目

主要功能:随机生成四则运算题目 设计思想:先通过一个简单的四则运算,再不断完善 源代码 #include"stdio.h" main(){ int a,b,c,d; printf("自动生成四则运算:\n"); printf("%d+%d= \n",a,b); printf("%d-%d= \n",a,b); printf("%d*%d= \n",a,b); printf("%d/%d= \n&q

作业1+2.四则运算(改进后完整版,用python写的)_064121陶源

概述: 用一个星期加上五一的三天假期自学了python,在Mac系统上重新写出了四则运算的程序,编译器是PyCharm,相当于完成了作业2.d)"选一个你从来没有学过的编程语言,试一试实现基本功能"这个方向. 用python写的这个程序能实现分数的加减程序,实现带加减乘除和括号的计算题,实现随机生成100道简单计算题,比之前用C++写的程序功能更加完善,更加简洁! 关键点: 调用两个模板. 1)类似C++和Java,格式是 对象.方法(),Fraction()方法,能直接表示分数. 2