C++学习随笔3 计算表达

1. 算术运算问题

中间结果溢出:

#include <iostream>
using namespace std;

int main()
{
    int a = 100000;
    int b = 100000;
    int c = 1000;

    cout<<a*b/c<<"\n";
    cout<<a*(b/c)<<"\n";    
}

输出结果:

1410065    (因为a*b = 1*1010 > 232=4294967296,所以a*b = 1*1010 % 4294967296 = 1410065408,所以a*b/c = 1410065408/1000=1410065)

10000000  (没有中间结果溢出,所以计算正常)

浮点数比较:

浮点数判断需要注意,float 和double 的精度范围,超过范围的数字会被忽略

(1)  浮点数大小判断
如果没有等号关系在里面,也就必然一大一小,那么直接用  > 或者 <

(2) 浮点数相等判断
因为浮点数在内存中存放,可能无法精确的储存,所以同一个值,可能有不同的内存数据,所以要使用以下的方法:
以float 为例,32位编译器中精度为有效位数为7,所以取 1e-7。
两个数字 A 、 B,
if ( |A-B| <1e-7 ) 则 A、B相等。

2. 相容类型转换

隐式转换:

如果一个int和一个unsigned long型数相乘,则先将两数都转换成double型数,再进行运算。

精度丢失:

由于参加运算的数据类型,可能先要转换成另外的数据类型(由低精度向高精度转换),进行中间运算,然后再转换回到低精度。因此,有一个从高精度数向低精度数转换的问题,转换中可能会引起精度丢失。

显示转换:

静态转换:static_cast<type>(表达式)

动态转换:dynamic_cast<type>(表达式)

常量转换:const_cast<type>(表达式)

重解释转换(一般用来转换不同类型指针): reinterpret_cast<type>(表达式)

指针的类型表明不同类型的指针,其类型不同,是不能互相赋值的。

例如:

float f = 34.5;

int *ip = &f;        //错:float的地址不能赋给int指针

但从地址值的本质来说,无非是用二进制表示的整数而已。因此从内存空间位置性而言,不同类型的指针又是统一的,都是二进制的地址。

int *ip = reinterpret_cast<int*>(&f);

该地址的空间不管放着什么数据,都将它作为整形看待。

3. 表达式的副作用

表达式在求值过程中引发了多于一个的实体值发生改变,称为表达式的副作用。

编译器相关:

例如:

int a=3, b=5;
int c = a*b + ++b;
cout<<c<<endl;

编译器有可能先计算a*b再计算++b,则c=3*5 + 6 = 21;

也有可能先计算++b,这时b的值已经更改再计算a*b,则c=3*6 + 6 = 24。

交换律失效:

c = a*b + ++b;

d = ++b + a*b;

由于副作用的存在,c和d的值无法相等。

括号失效:

int a =3,b=5;

int c = ++b * (a+b);

由于副作用的存在,括号失效。

消除副作用:

解决副作用的方法是分解表达式语句。

例如:

c=a*b+ ++b;写成

c = b + a*b;

b++;

或者

b++;

c = b + a*b;

posted @ 2016-11-24 18:31  etcjd  阅读(225)  评论(0)    收藏  举报