简单的算数运算和表达式
变量的类型决定了变量在内存中内存的字节数;
变量在内存中的存储方式(不同类型的变量合法的取值范围是不同的);
不同类型的变量参与的运算类型是不一样的;
问题:当算数运算符包含两个或两个以上的操作数时,根据什么确定运算顺序?
- 运算符的优先级
- 不同优先级时—从高到低运算
- 相同优先级时----二元算数运算符为左结合(从左到右)
举例:a = -3 * 2 - 1 + 3 ; 和 a = - (3 * 2 - 1 +3);
a = ((-3 )* 2) - 1 + 3 ; a= (-6)-1+3; a = - (6 - 1 + 3 );
a = (-7) + 3; a = - (5 + 3);
a = -4; a = -8;
巧妙使用圆括号改变运算符顺序-------------从内往外运算。
计算并输出一个三位整数的个位、十位、百位数字之和
如何分离个位、十位、百位数字?
153/100 = 1
153%10 = 3 (取余的计算) 153-1*100-5 * 10 = 3
153-1*100 = 53 153%100 = 53
53/10=5 153/10%10=5
**随机函数 rand() **
问题:怎样生成一个指定范围的随机数?
例题:生成一个在1~100之间的随机数?
magic = rand() % 100 + 1;
复合的赋值运算符
三种赋值形式:
- 简单赋值:变量 = 表达式 ;
- 多重赋值:变量1 = 变量2 =表达式 ;
赋值运算的结合性是右结合。
num = num + 5;
num += 5;
简单的赋值运算:例题:
已知a = 3;
执行 a += a -= a * a后,变量a的值?
a += a -= a * a
a += a -= 9
a += -6
a = -12
执行 a += a -= a *= a后,变量a的值?
a += a -= *a = a
a += a -= 9
a += 0
a = 0
n++,n–,++n,–n;
- ++让参与运算的变量加1,–让参与的运算减1;
- 作为前缀运算符时,先加/减1,在进行取值。
m = ++n; ------------->n = n + 1 ; m = n ;
- ++让参与运算的变量加1,–让参与的运算减1;
- 作为后缀运算符时,先取n的值,再进行加/减1的操作
m = n++; ------------------->m = n ; n = n + 1;
举例:对下面两种情况的比较
j = ++i - 2;
i = i + 1;
j = i - 2;
j = i++ - 2;
j = i - 2;
i = i + 1;
增1和减1的运算符:
int a = 3;
printf("%d",-a++);
printf("%d",-a);
a = a + 1;
良好的程序设计风格:在一行语句中,一个变量只出现一次增1或减1运算。
过多的增1减1会产生什么后果?
计算圆的周长和面积:
#include <stdio.h>
main()
{
printf("area = %f\n",3.14159*5.3*5.3);
printf("circumference = %f\n",2*3.14159*5.3);
}
在程序中直接使用的常数,成为“幻数”。
问题:使用幻数会存在哪些问题?
- 程序的可读性差,容易出现发生书写错误;
- 当常数需要改变时,要修改所有应用它的代码,还可能有遗漏。
如何避免在程序中使用幻数?
-
把幻数定义为常量(宏常量、const常量··· ···)
- 宏常量:也称“符号常量”。
计算圆的周长和面积:
#include <stdio.h>
#define PI 3.14159
#define R 5.3
main()
{
printf("area = %f\n",PI*R*R;
printf("circumference = %f\n",2*PI*R);
}
实际执行的程序是下面这个程序,两者之间是等价关系:宏替换
#include <stdio.h>
main()
{
printf("area = %f\n",3.14159*5.3*5.3);
printf("circumference = %f\n",2*3.14159*5.3);
}
- const常量
#include <stdio.h>
main()
{
const double pi = 3.14159;
const double r = 5.3;
printf("area = %f\n",pi*r*r);
printf("circumference = %f\n",2*pi*r);
}
问题:const常量与宏常量相比优点是什么?
- const有数据类型;
- 在某些集成化调试工具可以对const常量进行调试;
自动类型转换与强制类型转换
算数表达式中:
问题1:相同类型数据的运算结果的类型是什么?
举例:整数除法
11 / 5 = 2
问题2:不同类型数据的运算结果的类型是什么?
- 取值范围较大的那个类型;
- C编译器将所有的操作数都转换成占内存字节数最大的操作数的类型,称为“类型提升”。
举例:浮点数除法:
11.0 / 5 = 11.0 / 5.0 = 2.2
问题:类型提升的规则是什么?
double > float > long > int > short > char
从低到高进行转换----------自动类型转换(编译器在内部操作,用户无法感觉到)
必须的转换:
double<------float
int<—short(占两个字节)<–char(占一个字节)
double<----long<----unsigned<—int (由低向高)
都是由字节数低的向高的进行转换,这样会比较安全!反之,则会造成数据的丢失。
在不同数据类型之间赋值,是安全的嘛?
- 取值范围小的类型赋值给取值范围大的类型是安全的,反之是不安全的。
从高精度向低精度转换时,损失什么信息?
- 因低精度的数据位数比高精度的少,容纳不下高精度的所有信息,就会丢失信息,出现舍入,也称截断。
- 浮点数转为整数,会丢失小数部分,某些情况下整数部分精度也会损失。
双精度浮点数转为单精度,结果会怎样?
- 可能因有效数字位数不够而出现精度损失;
- 尾数所占位数决定实数的精度,不同系统下实数精度不同。
把表达式的值转为任意类型--------类型强转。 (类型)表达式
int x = 10;
float y;
y = (float)x;
问题:可能会出现浮点数的情况:
int total,number;
float average;
average = toatal/number;
int total,number;
float average;
average = (float)toatal/number;
对变量强转还是表达式强转的问题
m/2=2
(float)(m / 2) = 2.000000 //对表达式的结果进行强转
(float)m / 2 = 2.500000 // 对变量进行强转
m = 5
常用的标准数学函数
注意:使用标准数学函数时,要加入标准数学函数库,
#include <math.h>
常用的标准数学函数:
函数名 | 功能 |
---|
sqrt(x) | 计算x的平方根,x应该大于0 |
exp(x) | 计算e的x次方的值 |
fabs(x) | 计算x的绝对值 |
pow(x,y) | 计算x的y次方的值 |
log(x) | 计算lnx的值,x应该大于0 |
sin(x) | 计算sinx的值,x为弧度值,不是角度值 |
log10(x) | 计算lgx的值,x应该大于0 |
cos(x) | 计算cosx的值,x为弧度值,不是角度值 |
举例:计算三角形的面积
注:用海伦公式及计算
area = √s(s-a)(s-b)(s-c)
S = 2/1(a+b+c)
假设a,b,c定义为int型。
area =sqrt(s * (s-a) * (s-b) * (s - c)) //错误表达方式
area = aqrt(s(s - a) (s - b) (s -c)) //错误表达方式
s = 0.5 * (a+b+c) //正确表达方式
s = 1.0 / 2 * (a+b+c) //正确表达方式
s = (a+b+c) / 2.0 //正确表达方式
s = (float) (a+b+c) / 2 //正确表达方式
s = 1 / 2 * (a+b+c) //错误表达方式
s = (float)((a + b + c) / 2) //错误表达方式
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)