无符号整型被赋值负数的时候出现的陷阱、对图像数据进行操作时要注意数据类型的一致。

1、有没有人尝试过将负数赋给一个无符号整型变量?知不知道这样做会发生什么?还没有尝试的就让我们来探索下无符号整型隐藏的秘密。

先来看看下面代码:

int main()
{
      unsigned int val = -1;
      cout<<val<<endl;

      return 0;
}

执行的结果:

4294967295
请按任意键继续. . .

 

----------------------------------------

你可能禁不住惊叹:这么大!没想到吧,把一个负数赋值给无符号整型变量,会产生这么大的数!为啥呢?好,我们一步步分析:

首先,仔细观察输出的结果4294967295,发现4294967295=2^32-1,哦!好像有点规律!但是,又为啥会是这样?让我们先来讨论下int和unsigned int的表现形式,其中他俩都是4个字节,32位的二进制表示,但int有一位是符号位,unsigned则没有。那-1的int类型表示为1000 0000 0000 0000 0000 0000 0000 0001,那么将其强制转换成unsigned int 应该是1000 0000 0000 0000 0000 0000 0000 0001(红色为符号位),用指数表示是2^31+1,而不是2^32-1!这是怎么回事呢?(*^__^*) 嘻嘻……,这里还隐藏着一个小秘密!那就是int在真正存储在内存中的二进制数不是值的原码,而是其补码(为了便于运算,可以参考《数字逻辑》)!那么在强制类型转换之前,int变量-1内存中存储的是1111 1111 1111 1111 1111 1111 1111 1111,等于2^32-1。soso在强转为unsigned int时,就是读取该块内存的值赋给变量!这样val就变成了4294967295,超级大的数!所以各位同仁在处理unsigned int 赋值时一定要谨慎!如果出错将影响甚大,因为unsigned int一般都会作为for或while循环体的标识类型,如果将负值赋给它,将导致严重的假死循环!痛哉!痛哉!

2、负数的补码:负数的补码是对其原码逐位取反,但符号位除外;然后整个数加1。

同一个数字在不同的补码表示形式里头,是不同的。比方说-15的补码,在8位2进制里头是11110001,然而在16位2进制补码表示的情况下,就成了1111111111110001。在这篇补码概述里头涉及的补码转换默认把一个数转换成8位2进制的补码形式,每一种补码表示形式都只能表示有限的数字。

【例2】求-7的补码。

因为给定数是负数,则符号位为“1”。取反加一

后七位:-7的原码(10000111)→按位取反(11111000)(负数符号位不变)→加1(11111001)

所以-7的补码是11111001。

3、正数的补码:正数的补码是其原身。

与原码相同。

【例1】+9的补码是00001001。(备注:这个+9的补码说的是用8位的2进制来表示补码的,补码表示方式很多,还有16位2进制补码表示形式,以及32位2进制补码表示形式等。)

4、对相同符号的不同类型的数据进行赋值,则不会出现数据变化的情况,

例如:

	int hh = 0;
	hh = (double)-818.626381968738; //hh结果是-818,其是舍弃后面的,而不会进行几舍几入运算的。
6、虽然上面的进行相同符号的取值赋值时不会出现错误,但是opencv如果是不同数据类型进行操作的话则会出现错误,有的是不会报错,但数据不对。

其正确的读取方法是:

         Mat camera_matrix = Mat(3, 3, CV_64FC1, camD);     //定义的图像是64位的double型
         Mat distortion_coefficients = Mat(5, 1, CV_64FC1, distCoeffD);
	if (first == false){
	first = true;
	cvSave("Intrinsics.xml", &CvMat(camera_matrix));
	cvSave("rotation.xml", &CvMat(rotM));
	cvSave("translation.xml", &CvMat(tvchange));
	}

	float fx=0, fy=0, cx=0, cy=0, k1, k2, p1, p2, k3;  //define intrinsic, distortion_coeff
	float r11, r12, r13, r21, r22, r23, r31, r32, r33; //rotation matrix
	float t1, t2, t3;

	CvMat *intrinsic_matrix = (CvMat*)cvLoad("Intrinsics.xml");
	CvMat *rotation_mat_final = (CvMat*)cvLoad("rotation.xml");
	CvMat *translation_vector = (CvMat*)cvLoad("translation.xml");

	fx = CV_MAT_ELEM(*intrinsic_matrix, float, 0, 0);    //读取的值是错误的,但是程序不会报错,其是由于数据类型跟存储的不同一个是double,一个是float。
	fy = CV_MAT_ELEM(*intrinsic_matrix, double, 1, 1);   //读取的值是正确的。
	cx = CV_MAT_ELEM(*intrinsic_matrix, double, 0, 2);
	cy = CV_MAT_ELEM(*intrinsic_matrix, double, 1, 2);

        float hh = 0;
	hh = (double)-818.626381968738;    //但是这个直接赋值的却是正确的,其hh为-818.626381被舍弃了一些数据位。










  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值