意想不到的除数为零
最后更新于:2022-04-01 06:40:32
##没有躲过的坑--意想不到的除数为零
工程中有这样一个需求,需要获得一张图片的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取整的。