牛骨文教育服务平台(让学习变的简单)

没有躲过的坑--意想不到的除数为零

工程中有这样一个需求,需要获得一张图片的width和height,然后等比例的显示这张图片。

首先是获得得到一张图片的路径,然后计算出他的width和height,然后计算:

int resize_width = 160;
int resize_height = 160;
if (image_width > image_height) {
    resize_width = 160;
    resize_height = 160 * image_height / image_width;
}
else {
    resize_height = 160;
    resize_width = 160 * image_width / image_height;
}

很多情况下 ,我们都可以如愿以偿。

但是情况总有特俗,这就看你是如何计算一张图片的width和height的了,之前Google过一个方法只能计算24k大小以上的图片。

当图片过大或是过小,我们使用的方法无法计算这张图片的width和height时,情况出现了。

我们从小就知道除法中除数不能为零,但是在编程过程中往往忽略这一点。加之测试不够,往往会挖下一个很大的坑儿。

因此修改上面的代码:

int resize_width = 0;
    int resize_height = 0;
    if (image_width == 0 || image_height == 0)
    {
        resize_width = 160;
        resize_height = 160;
    }
    else
    {
        if (image_width > image_height) {
            resize_width = 160;
            resize_height = 160 * image_height / image_width;
        }
        else {
            resize_height = 160;
            resize_width = 160 * image_width / image_height;
        }
    }

对width和height是否为零进行判断。

说道除法,那就继续写点。 
C++中的大多数二元操作都要求两个操作数是同一类型。如果操作数的不同类型,其中一个操作数会提升到和另一个操作数相匹配的类型。在C++中,除法操作符可以被看做是2个不同的操作:其中一个操作于整数之上,另一个是操作于浮点数之上。如果操作数是浮点数类型,除法操作将返回一个浮点数的值:

float fX = 7;
float fY = 2;
float fValue = fX / fY; 
// fValue = 3.5

如果操作数是整数类型,除法操作将丢弃任何小数部分,并只返回整数部分。

int  nX = 7;
int nY = 2;
int nValue = nX / nY;   
//  nValue = 3

如果一个操作数是整型,另一个操作数是浮点型,则整型会提升为浮点型:

float fX = 7.0;
int nY = 2;
float fValue = fX / nY;

// nY 提升为浮点型,除法操作将返回浮点型值
// fValue = 3.5

有很多人会想当然:

int nX = 7;
int nY = 2;
float fValue = nX / nY;  
// fValue = 3(不是3.5哦!)

这里的本意是nX/nY将产生一个浮点型的除法操作,因为结果是赋给一个浮点型变量的。但实际上并非如此。nX/nY首先被计算,结果是一个整型值,然后才会提升为浮点型并赋值给fValue。但在赋值之前,小数部分就已经丢弃了。

要强制两个整数采用浮点型除法,其中一个操作数需要类型转换为浮点数:

int nX = 7;
int nY = 2;
float fValue = static_cast<float>(nX) / nY;  
// fValue = 3.5

因为nX显式的转换为float型,nY将隐式地提升为float型,因此除法操作符将执行浮点型除法,得到的结果就是3.5。

有关整数除法的另一个有趣的事情是,当一个操作数是负数时C++标准并未规定如何截断结果。造成的结果就是,编译器可以自由地选择向上截断或者向下截断!比如,-5/2可以既可以计算为-3也可以计算为-2,这和编译器是向下取整还是向0取整有关。大多数现代的编译器是向0取整的。