《linux c编程一站式学习》笔记1

1 复数及程序实现

来自《linux c编程一站式学习》 7.2节第1题:在本节的基础上实现一个打印复数的函数,打印的格式是 x+yi,如果实部或虚部为0则省略,例如:1.0、-2.0i、-1.0+2.0i、1.0-2.0i。最后编写一个main函数测试本节的所有代码。

-----------------------------------------------

#include <math.h>
#include <stdio.h>
struct complex_struct {
  double x, y;
};


double real_part(struct complex_struct z)
{
  return z.x;
}


double img_part(struct complex_struct z)
{
  return z.y;
}


double magnitude(struct complex_struct z)
{
  return sqrt(z.x * z.x + z.y * z.y);
}


double angle(struct complex_struct z)
{
  return atan2(z.y, z.x);
}


struct complex_struct make_from_real_img(double x, double y)
{
  struct complex_struct z;
  z.x = x;
  z.y = y;
  return z;
}


struct complex_struct make_from_mag_ang(double r, double A)
{
  struct complex_struct z;
  z.x = r * cos(A);
  z.y = r * sin(A);
  return z;
}


struct complex_struct add_complex(struct complex_struct z1, struct complex_struct z2)
{
  return make_from_real_img(real_part(z1) + real_part(z2), img_part(z1)  + img_part(z2));
}


struct complex_struct sub_complex(struct complex_struct z1, struct complex_struct z2)
{
  return make_from_real_img(real_part(z1) - real_part(z2), img_part(z1)  -  img_part(z2));
}


struct complex_struct mul_complex(struct complex_struct z1, struct complex_struct z2)
{
  return make_from_mag_ang(magnitude(z1) * magnitude(z2), angle(z1) + angle(z2));
}


struct complex_struct div_complex(struct complex_struct z1, struct complex_struct z2)
{
  return make_from_mag_ang(magnitude(z1) / magnitude(z2),   angle(z1) - angle(z2));
}


void print_complex(struct complex_struct z)
{
        if (z.x==0 && z.y ==0)
                printf("0\n");
        else if (z.x==0 && z.y!=0)
                printf("%fi\n",z.y);
        else if (z.x!=0 && z.y==0)
                printf("%f\n",z.x);
        else
                printf("%f + %fi\n", z.x, z.y);
}




int main(void)
{
        struct complex_struct z1 = {3.0, 4.0};
        struct complex_struct z2 = {3.0, 6.0};
        struct complex_struct z;
        z = add_complex(z1, z2);
        print_complex(z);
        z = sub_complex(z2, z1);
        print_complex(z);
        struct complex_struct z3 = {6.0, 3.0};
        z = mul_complex(z2, z3);
        print_complex(z);
        z = div_complex(z3, z2);
        print_complex(z);
        return 0;
}

程序的输出如下:
[root@redhat-beijing test]# gcc -Wall -lm complex_struct.c -o complex_struct
[root@redhat-beijing test]# ./complex_struct 
6.000000 + 10.000000i
2.000000i
0.000000 + 45.000000i
0.800000 + -0.600000i


---------------改用极坐标来存储----------------
#include <stdio.h>
#include <stdlib.h>
#include <math.h>


struct complex_struct {
        double r, A;
};


double real_part(struct complex_struct z)
{
        return z.r * cos(z.A);
}


double img_part(struct complex_struct z)
{
        return z.r * sin(z.A);
}
double magnitude(struct complex_struct z)
{
        return z.r;
}


double angle(struct complex_struct z)
{
        return z.A;
}


struct complex_struct make_from_real_img(double x, double y)
{
        struct complex_struct z;
        z.A = atan2(y, x);
        z.r = sqrt(x * x + y * y);
        return z;
}


struct complex_struct make_from_mag_ang(double r, double A)
{
        struct complex_struct z;
        z.r = r;
        z.A = A;
        return z;
}
struct complex_struct add_complex(struct complex_struct z1, struct complex_struct z2)
{
        return make_from_real_img(real_part(z1) + real_part(z2),
                                  img_part(z1) + img_part(z2));
}


struct complex_struct sub_complex(struct complex_struct z1, struct complex_struct z2)
{
        return make_from_real_img(real_part(z1) - real_part(z2),
                                  img_part(z1) - img_part(z2));
}


struct complex_struct mul_complex(struct complex_struct z1, struct complex_struct z2)
{
        return make_from_mag_ang(magnitude(z1) * magnitude(z2),
                                 angle(z1) + angle(z2));
}


struct complex_struct div_complex(struct complex_struct z1, struct complex_struct z2)
{
        return make_from_mag_ang(magnitude(z1) / magnitude(z2),
                                 angle(z1) - angle(z2));
}


//打印复数 属于复数运算层,调用复数表示层
void printf_complex(struct complex_struct z)
{
        if(abs(real_part(z))<0.1&&abs(img_part(z))>=0.1)        //浮点型不能直接判断是否为0,这里因为输出只保留小数点后1位,所以认为小于0.1的就为0
                        printf("%.1fi\n",img_part(z));
        else if(abs(real_part(z))>=0.1&&abs(img_part(z))<0.1)
                        printf("%.1f\n",real_part(z));
        else if(abs(real_part(z))<0.1&&abs(img_part(z))<0.1)
                        printf("0\n");
        else
                printf("%.1f+%.1fi\n",real_part(z),img_part(z));
}
int main(void)
{
        struct complex_struct z1=make_from_real_img(0,2);
        struct complex_struct z2=make_from_real_img(0,1);
        printf("z1+z2=");       printf_complex(add_complex(z1,z2));
        printf("z1-z2=");       printf_complex(sub_complex(z1,z2));
        printf("z1*z2=");       printf_complex(mul_complex(z1,z2));
        printf("z1/z2=");       printf_complex(div_complex(z1,z2));
        return 0;
}
程序输出:
[root@redhat-beijing test]# gcc -Wall -lm complex_struct.c -o complex_struct
[root@redhat-beijing test]# ./complex_struct 
z1+z2=3.0i
z1-z2=1.0i
z1*z2=-2.0
z1/z2=2.0
[root@redhat-beijing test]# 




--------------以下为复数的知识-----------------

复数,为实数的延伸,它使任一多项式方程式都有。复数当中有个“虚数单位i,它是-1的一个平方根,即i ^2 = -1。任一复数都可表达为x + yi,其中xy皆为实数,分别称为复数之“实部”和“虚部”。

欧拉公式:

\cos \theta + i \sin \theta = e ^{i \theta}

符号表示

尽管可以使用其他表示法,复数通常写为如下形式

 a + bi

这里的ab实数,而i虚数单位,它有着性质i ² = −1。实数a叫做复数的实部,而实数b叫做复数的虚部。实数可以被认为是虚部为零的复数;就是说实数a等价于复数a+0i。实部为零且虚部不为零的复数也被称作“纯虚数”。


运算

通过形式上应用代数的结合律交换律分配律,再加上等式i ² = −1,定义复数的加法、减法、乘法和除法:


从极坐标形式到笛卡儿坐标形式的转换

x = r \cos \varphi
y = r \sin \varphi

从笛卡尔坐标形式到极坐标形式的转换

r = \sqrt{x^2+y^2}
\varphi =\begin{cases}\arctan(\frac{y}{x}) & \mbox{if } x > 0\\\arctan(\frac{y}{x}) + \pi & \mbox{if } x < 0 \mbox{ and } y \ge 0\\\arctan(\frac{y}{x}) - \pi & \mbox{if } x < 0 \mbox{ and } y < 0\\+\frac{\pi}{2} & \mbox{if } x = 0 \mbox{ and } y > 0\\-\frac{\pi}{2} & \mbox{if } x = 0 \mbox{ and } y < 0\\\mathrm{undefined} & \mbox{if } x = 0 \mbox{ and } y = 0.\end{cases}

前面的公式要求非常繁杂的情况区分。但是很多编程语言提供了经常叫做atan2一个变体的反正切函数来处理这些细节。使用反余弦函数的公式要求更少的情况区分:

\varphi =\begin{cases}+\arccos\frac{x}{r} & \mbox{if } y \geq 0 \mbox{ and } r \ne 0\\-\arccos\frac{x}{r} & \mbox{if } y < 0\\\mathrm{undefined} & \mbox{if } r = 0.\end{cases}

极坐标形式的符号

极坐标形式的符号

 z = r\,(\cos \varphi + i\sin \varphi )

被叫做“三角形式”。有时使用符号cis φ简写cosφ + isinφ。 使用欧拉公式还可以写为

 z = r\,\mathrm{e}^{i \varphi}\,,

这叫做“指数形式”。

极坐标形式下的乘法、除法、指数和开方根

在极坐标形式下乘法、除法、指数和开方根要比笛卡尔形式下容易许多。

使用三角恒等式得到

r_1\,e^{i\varphi_1} \cdot r_2\,e^{i\varphi_2}= r_1\,r_2\,e^{i(\varphi_1 + \varphi_2)}

\frac{r_1\,e^{i\varphi_1}}{r_2\,e^{i\varphi_2}} = \frac{r_1}{r_2}\,e^{i (\varphi_1 - \varphi_2)}

依据棣莫弗定理做整数幂的指数运算,

\big(r\,e^{i\varphi}\big)^n = r^n\,e^{in\varphi}


2 分数及结构体实现

实现一个用分子分母的格式来表示有理数的结构体rational以及相关的函
数,rational结构体之间可以做加减乘除运算,运算的结果仍然是rational。
测试代码如下: 
int main(void) 

  struct rational a = make_rational(1, 8); /* a=1/8 */ 
  struct rational b = make_rational(-1, 8); /* b=-1/8 */ 
  print_rational(add_rational(a, b)); 
  print_rational(sub_rational(a, b)); 
  print_rational(mul_rational(a, b)); 
  print_rational(div_rational(a, b)); 
 
  return 0; } 
注意要约分为最简分数,例如1/8和-1/8相减的打印结果应该是1/4而不是2/8,
可以利用第 3 节 “递归”练习题中的Euclid算法来约分。在动手编程之前先思
考一下这个问题实现了什么样的数据抽象,抽象层应该由哪些函数组成。


#include <stdio.h>
#include <stdlib.h>


struct rational {
        int a,b;
};


struct rational make_rational(int a,int b)
{
        struct rational z;
        z.a=a;
        z.b=b;
        return z;
}


struct rational add_rational(struct rational a,struct rational b)
{
        struct rational c;
        c.a=a.a*b.b+a.b*b.a;
        c.b=a.b*b.b;
        return c;
}


struct rational sub_rational(struct rational a,struct rational b)
{
        struct rational c;
        c.a=a.a*b.b-a.b*b.a;
        c.b=a.b*b.b;
        return c;
}


struct rational mul_rational(struct rational a,struct rational b)
{
        struct rational c;
        c.a=a.a*b.a;
        c.b=a.b*b.b;
        return c;
}


struct rational div_rational(struct rational a,struct rational b)
{
        struct rational c;
        c.a=a.a*b.b;
        c.b=a.b*b.a;
        return c;
}
int gcd (int a,int b)
{
        if(b==0)
                return abs(a);
        else
                return gcd(b,a%b);
}


void print_rational(struct rational a)
{
        int ra_gcd=gcd(a.a,a.b);
        a.a=a.a/ra_gcd;
        a.b=a.b/ra_gcd;
        if(a.a==0)
                printf("0\n");
        else if(abs(a.b)==1)
                printf("%d\n",a.a/a.b);
        else
                printf("%d/%d\n",a.a,a.b);
}
int main(int argc, char* argv[])
{
        struct rational a = make_rational(1, 8); /* a=1/8 */
        struct rational b = make_rational(-1, 8); /* b=-1/8 */
        print_rational(add_rational(a, b));
        print_rational(sub_rational(a, b));
        print_rational(mul_rational(a, b));
        print_rational(div_rational(a, b));
        return 0;
        system("pause");
}
程序的输出:
[root@redhat-beijing test]# gcc -Wall -lm rational.c -o rational
[root@redhat-beijing test]# ./rational 
0
1/4
-1/64
-1
[root@redhat-beijing test]# 









  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值