博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【C语言学习趣事】_33_关于C语言和C++语言中的取余数(求模)的计算_有符号和无符号数的相互转换问题...
阅读量:6273 次
发布时间:2019-06-22

本文共 4324 字,大约阅读时间需要 14 分钟。

     最近再次复习C++语言,用的教材是《C++ Primer》这本教材, 看到第二章的时候,里面有个问题困扰了我。

于是想上网查查怎么回事, 结果看了很久都没有得到一个满意的答案。

    书上有这么一段话:当将一个超出数据类型取值范围的值赋值给这个类型的一个变量时,变量的值的结果由变量的

类型决定。

   后面还有这么一段解释:

   1、当接受值的变量类型为无符号类型时,  变量的值 =  超出变量范围的值 % 类型可以表示的数值的个数

Exp:

unsigned char nTest;nTest = 343;

那么这样nTest的值就可以用下面的方式进行计算:

  nTest = 343 % 256 = 343 - 256 = 87    //中间的343-256 是计算方便,实际上没有这种转换方式

我在RHEL中测试的结果如下:

[root@localhost cpp_src]# cat test.cpp #include 
int main(){ unsigned char nTest; unsigned int n; nTest = 343; n=nTest; std::cout<<"nTest="<
<
[root@localhost cpp_src]# g++ test.cpp test.cpp: In function ‘int main()’:test.cpp:7: 警告:大整数隐式截断为无符号类型[root@localhost cpp_src]# ./a.out nTest=Wn=87343%256=87

  可以看到测试的时候,对截断数据进行了提示,而且最终得到的结果也是这么计算的。

  让我迷惑的不是上面的过程,上面的过程非常的自然。令我迷惑的是下面的情况:

    当接受值的变量类型为无符号型,而赋给它的值是一个负数,该如何处理。

Exp:

unsigned char nTest;nTest = -1;

  按照上面的说法:   nTest = -1 % 256 ;  

     问题就出在这个地方,对于负数的求余数,我们该怎么求呢?以前从来没注意这个问题,

这次就想一定要弄明白。

[root@localhost cpp_src]# cat test.cpp #include 
int main(){ unsigned char nTest; unsigned int n; nTest = -1; n=nTest; std::cout<<"nTest="<
<

执行结果为:

[root@localhost cpp_src]# g++ test.cpp [root@localhost cpp_src]# ./a.out nTest=�n=255-1%256=-1

  经过这个地方的计算,我们并不能得到什么规律,但是我们发现一个问题:  n= 255 = 256 + (-1) 

256 是unsigned char 可以表示的数值的个数(8bit可以表示256个数), 而 -1 是 -1 % 256 后得到的余数。

于是我就继续做了几个实验:

[root@localhost cpp_src]# cat test.cpp #include 
int main(){ unsigned char nTest; unsigned int n; nTest = -367; n=nTest; std::cout<<"nTest="<
<

执行结果为:

[root@localhost cpp_src]# g++ test.cpp test.cpp: In function ‘int main()’:test.cpp:7: 警告:大整数隐式截断为无符号类型[root@localhost cpp_src]# ./a.out nTest=�n=145-367%256=-111

分析:  n=145 = 256 + (-367%256)= 256 + (-111) = 145;

还有下面的实验:

#include 
int main(){ unsigned char nTest; unsigned int n; nTest = -1000; n=nTest; std::cout<<"nTest="<
<

执行结果如下所示:

[root@localhost cpp_src]# g++ test.cpp test.cpp: In function ‘int main()’:test.cpp:7: 警告:大整数隐式截断为无符号类型[root@localhost cpp_src]# ./a.out nTest=n=24-1000%256=-232

分析也是:  n = 24 = 256 + (-1000 % 256) = 256 + (-232) = 24 ;

于是我得到一个结论:

  无符号变量的值 = 类型可以取值的个数 + (负数 % 类型可以取值的个数)

例如8bit的计算公式为:

     无符号变量的值 = 256 + (负数 % 256 )

下面通过代码进行测试:

#include 
int main(){ unsigned char nTest; unsigned int n; int i; unsigned int j; for(i=0;i<=10;i++) { nTest = -1000+i; j=nTest; n=256 +( (-1000+i) % 256); std::cout<<"nTest="<
<

测试结果为:

[root@localhost cpp_src]# g++ test.cpp [root@localhost cpp_src]# ./a.out nTest=j=24n=24nTest=j=25n=25nTest=j=26n=26nTest=j=27n=27nTest=j=28n=28nTest=j=29n=29nTest=j=30n=30nTest=j=31n=31nTest= j=32n=32nTest=!j=33n=33nTest="j=34n=34

  通过上面的测试,可以证明我的猜想是正确的。

  接下来的问题如何求取这个余数,因为以前都没考虑过这个问题。我们这里再次来进行猜想:

我们知道 -1000  % 256 = - 232,而  1000/256*256 + (-1000) = -232

            -1       % 256  = -1        而 1     /256*256 + (-1) = -1

因此我们这样进行猜想求模公式为:

   负数 % 变量类型可以表示数的个数  = 负数 * (-1) / 变量类型可以表示数的个数 * 变量类型可以表示数的个数 + 负数

下面我们用代码进行测试,验证上面的公式是否正确。

#include 
int main(){ int n,k; for(int i=0;i<=10;i++) { n=(-1000+i)%256; k = (-1000 + i)*(-1)/256*256 + (-1000+i); std::cout<<"n="<
<

执行结果如下

[root@localhost cpp_src]# g++ mod.cpp [root@localhost cpp_src]# ./a.out n=-232k=-232n=-231k=-231n=-230k=-230n=-229k=-229n=-228k=-228n=-227k=-227n=-226k=-226n=-225k=-225n=-224k=-224n=-223k=-223n=-222k=-222

  可以发现我的猜想与实际的结果一样,因此可以确定这种方法是对的。

 

小结:

  1、 当用正数赋值给无符号数时,如果正数在无符号数表示的值范围内时直接赋值。

           当用正数赋值给无符号数时,如果正数不在无符号数表示的值范围, 即正数 》 表示的值的范围 , 

          得到的结果为:  无符号变量 = 正数的值 % 无符号数类型可以表示的值个数

      2、当用负数给无符号数赋值时, 

    无符号变量的值 = 类型可以取值的个数 + (负数 % 类型可以取值的个数)

  3、负数 % 正数 的求模公式

             负数 % 类型可以取值的个数  = 负数 * (-1) / 类型可以取值的个数* 类型可以取值的个数 + 负数

 

    结合上面的第二条和第三条就可以得到有符号数给无符号数赋值时的最终求值公式。

   无符号变量的值 =  类型可以取值的个数 + 负数 * (-1) / 类型可以取值的个数 * 类型可以取值的个数 + 负数

 

  可以利用上面的公式进行测试:   

unsigned char n;unsigned int k;n = -171;k=n;

程序的执行结果如下:

[root@localhost cpp_src]# g++ test.cpp test.cpp: In function ‘int main()’:test.cpp:8: 警告:大整数隐式截断为无符号类型[root@localhost cpp_src]# ./a.out n=Uk=85

用手代入公式计算:

  无符号变量的值 =  类型可以取值的个数 + 负数 * (-1) / 类型可以取值的个数 * 类型可以取值的个数 + 负数

      n = 256 + (-171)* -1 / 256 * 256 + (-171)  = 85

结果正确。

     

    至此,本次问题的讨论到此结束,如果您有更好的计算方法,请您不吝赐教。

如果您觉得我说的不正确,也请您不吝赐教。

 

转载于:https://www.cnblogs.com/volcanol/p/3987121.html

你可能感兴趣的文章
Debian 项目领导人职位已有三位侯选者
查看>>
阿里巴巴与三个知名车企达成合作,将为其“AI+车”解决方案
查看>>
django小项目:搭建简易火车车票预订系统
查看>>
仅研发就投入3300人 华为如何掘金物联网?
查看>>
表单调试工具推荐
查看>>
Kubernetes node的防火墙问题导致pod ip无法访问
查看>>
hdfs-site.xml配置
查看>>
为什么多线程读写 shared_ptr 要加锁?
查看>>
netware 6.5的故障解决
查看>>
linux 同步IO: sync、fsync与fdatasync
查看>>
笼络人才,再三“表白”,库克表示苹果更看重AR
查看>>
[原创]对于运行ASP.NET程序时,提示:无法启动程序“http://localhost:3532/Default.aspx”。的疑问...
查看>>
潮鞋的AR初体验,鬼冢虎和Anrealage合作新鞋
查看>>
4星|《错误的行为》:经济行为中大部分时候人们是不理性的
查看>>
java中包容易出现的错误及权限问题
查看>>
Hibernate5-查询与排序
查看>>
硬盘速度测试
查看>>
mouseout、mouseover和mouseleave、mouseenter区别
查看>>
一句话命令
查看>>
TCP/IP
查看>>