第二章:变量和基本类型 练习2.1 类型 int、long、long long 和 short 的区别是什么?无符号类型和带符号类型的区别是什么?float 和 double的区别是什么?
C++ 规定 short
和 int
至少16位,long
至少32位,long long
至少64位。 带符号类型能够表示正数、负数和 0 ,而无符号类型只能够表示 0 和正整数。 通常,单精度float
用1个字表示(4个字节,32bit),双精度double
用2个字表示(8个字节,64bit)。
用法(类型的选择):
如果确认数据是非负的,那么就使用 unsigned
无符号类型。 一般使用 int
做整数运算,short
因为太小在实际中用的少,long
通常和 int
有着相同的大小。如果数据非常大,可以使用 long long
。 算术表达式不用 char
或 bool
,这二者只建议用于存放字符或布尔值。因为char
在某些机器上是有符号的,在另一些机器上是无符号型的,则使用 char
进行运算容易出问题。如果需要较小的整数,就明确指定 signed char
或者 unsigned char
。 执行浮点运算时用 double
,因为 float
通常精度不够而且双精度浮点数和单精度浮点数的计算代价相差无几。 参考:
float有效位理解 IEEE规定float
为32bit,尾数用23位存储,加上隐含的小数点前的1位1,2^(23+1) = 16777216。因为 10^7 < 16777216 < 10^8,所以说单精度浮点数的有效位数是7位(能保证7位有效数字,当然,并非说第8位一定是非有效数字,它也有可能是准确的)。
1 2 3 4 5 6 7 8 9 #include <stdio.h> int main () { float i = 12345678.76348 ; float j = 46857.9874 ; printf ("%f\n%f\n%.3f\n%.8f" , i, j, j, j); return 0 ; }
输出:
1 2 3 4 12345679.000000 46857.988281 46857.988 46857.98828125
从以上数据可以看出,第八个数字之后就不精确了。另外,要注意,有效数字的位数与指定输出的小数位数(%.7f,保留7位有效数字)是两码事,如第三第四个输出,这个是程序指定的输出格式,和类型本身能够存储的精度不是一回事。
C++算术类型 类型 含义 最小尺寸 bool 布尔类型 未定义 char 字符 8位 wchar_t 宽字符 16位 char16_t Unicode字符 16位 char32_t Unicode字符 32位 short 短整型 16位 int 整型 16位 long 长整型 32位 long long 长整型 64位 float 单精度浮点数 6位有效数字 double 双精度浮点数 10位有效数字 long double 扩展精度浮点数 10位有效数字
练习2.2 计算按揭贷款时,对于利率、本金和付款分别应选择何种数据类型?说明你的理由。
使用 double
或 float
。
练习2.3 读程序写结果。
1 2 3 4 5 6 7 8 unsigned u = 10 , u2 = 42 ;std::cout << u2 - u << std::endl; std::cout << u - u2 << std::endl; int i = 10 , i2 = 42 ;std::cout << i2 - i << std::endl; std::cout << i - i2 << std::endl; std::cout << i - u << std::endl; std::cout << u - i << std::endl;
输出:
1 2 3 4 5 6 32 4294967264 // -32=(-1)×2^32+4294967264 32 -32 0 0
类型转换的总结 非布尔类型转换布尔类型时,0转换成false,非0则true(包括负数)。 布尔值转换非布尔类型时,false转换为0,true则1。 浮点数转换整数时,仅保留小数点之前的部分(即整数部分,小数部分直接截断),这是精度损失;当浮点数表示的值大过整型值,会发生溢出。 整数转浮点数时,小数部分记为0。不会发生溢出,但当整数值数据较大时,转换浮点数可能会发生精度丢失。例如,int
有31bit用来拓展精度,float
只有24bit,即当int值大于2^24或者小于-2^24时,转换float
就会精度丢失。 给无符号类型赋值超过其表示范围时,实际值是初始值对无符号类型表示数值总数取模后的余数。8bit的unsigned char
表示0-255,赋值超出范围时,实际值为该值对256取模后的余数。因此将-1赋给8bit的unsigned char
时,结果值为255。 赋给带符号类型一个超出范围的值时,结果是未定义的。此时,程序可能工作、可能崩溃、也可能生成垃圾数据。 无符号类型和有符号类型计算,结果为负数时,结果值的计算方法
给定一个正整数p,任意一个整数n,一定存在等式n=kp+r
其中k、r是整数,且0<=r<p,称k为n除以p的商,r为n除以p的余数。
定义取模运算:a % p(或a mod p),表示a除以p的余数。
实际运用场景 :将-1赋给8bit的unsigned char
时,结果值为255。 计算过程:-1=(-1)×256+255
二进制表示的本质:用补码表示,先看原码(符号位为1,数值位只有一个1)对原码取反加1(符号位不变),转换成补码后,所有位都是1。
类型转换的使用场景总结 不要混用带符号类型和无符号类型:表达式中含有这两种类型时,带符号数会自动转换成无符号数(此时,一个负数转换成无符号数后,真值将很大)。 循环中的判断条件慎用无符号数:无符号数表示范围为正整数,不会小于0,尤其是当循环的临界条件是0时。如以下代码,就是死循环,当u=0时,循环条件依然满足,继续执行,--u就是-1,但无符号数只能表示整数,-1被自动地转换成一个合法的无符号数,即正整数。 1 2 for (unsigned u = 10 ; u >= 0 ; --u) std::cout << u << std::endl;
解决方式:
用有符号类型 用while语句,代码如下。 类似while语句,将for语句的--u置于cout语句中。 2和3本质上就是保证u不会变为-1。 1 2 3 4 5 6 unsigned u = 11 ;while (u > 0 ){ --u; std::cout << u << std::endl; }
编写程序检查你的估计是否正确,如果不正确,请仔细研读本节直到弄明白问题所在。