zoukankan      html  css  js  c++  java
  • 基本类型间的类型转换(数值型)

    今天一打开博客,看到左上角的园龄5年,目光有些恍然,昔日作为学生上课的情景、已经慢慢变的模糊。是啊、毕业已经3年有余,时光不再来...

    一、原码和补码

    在步入正文说类型转换之前,先做一个小铺垫,了解一下原码和补码。

    [注:由于同一个数字在用不同位数的原码或补码表示时、结果不同,所以如无特殊说明、该小节下出现的所有原码和补码均为8位]

    原码(true form)是一种计算机中对数字的二进制定点表示方法。原码表示法在数值前面增加了一位符号位(即最高位为符号位):

    正数该位为0,负数该位为1(0有两种表示:+0和-0),其余位表示数值的大小。

    1、原码优点:简单直观;例如,我们用8位二进制表示一个数,+11的原码为00001011,-11的原码就是10001011

    2、原码缺点:原码不能直接参加运算,可能会出错。例如数学上,1+(-1)=0,而在二进制中 00000001+10000001=

    10000010,换算成十进制为-2。显然出错了。

    补码(two's complement) 在计算机系统中,数值一律用补码来表示和存储。补码是可以直接参与运算的。原码和补码表示方法均有

    符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位表示方法不相。

    1、知原码求补码

    求正数的补码:正整数的补码与原码相同。

    【例】+9的补码是00001001。

    求负数的补码:求负整数的补码, 在原码的基础之上 符号位不变,数值位各位取反,最后整个数加1。

    【例】求-5的补码。
    -5的原码(10000101)→符号位不变(10000101)→数值位取反(11111010)→加1(11111011)
    所以-5的补码是11111011。
    【例】数0的补码表示是唯一的。
    [+0]补=[+0]原=00000000
    [-0]补=11111111+1=00000000


    2、知补码求原码

    已知一个数的补码,求原码的操作其实就是对该补码再求补码:
    1)如果补码的符号位为“0”,表示是一个正数,其原码就是补码。
    2)如果补码的符号位为“1”,表示是一个负数,那么求给定的这个补码的补码就是要求的原码。
    【例】已知一个补码为11111001,则原码是10000111(-7)。
    因为符号位为“1”,表示是一个负数,所以该位不变,仍为“1”。
    其余七位1111001取反后为0000110;
    再加1,所以是10000111。

    3、补码的运算

     补码:http://baike.baidu.com/view/377340.htm

     

    二、整形间的类型转换

        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("注:该demo中的所有例子均为整形间的无精度损失的类型转换,为了方便阅读打印的是字节而不是位");
                Console.WriteLine("1、补位式转化");
    
                Console.WriteLine("
    ###32位有符号 转 64位无符号###");
                Console.WriteLine("
    例1");
                int i = int.MaxValue;
                ulong ul = (ulong)i;
                Print(BitConverter.GetBytes(i), i.ToString(), "转化前");
                Print(BitConverter.GetBytes(ul), ul.ToString(), "转化后");
                Console.WriteLine("
    例2");
                i = int.MinValue;
                ul = (ulong)i;
                Print(BitConverter.GetBytes(i), i.ToString(), "转化前");
                Print(BitConverter.GetBytes(ul), ul.ToString(), "转化后");
    
                Console.WriteLine("
    ###32位有符号 转 64位有符号###");
                Console.WriteLine("
    例3");
                i = int.MinValue;
                long l = (long)i;
                Print(BitConverter.GetBytes(i), i.ToString(), "转化前");
                Print(BitConverter.GetBytes(l), l.ToString(), "转化后");
    
    
                Console.WriteLine("
    ###32位无符号 转 64位有符号###");
                Console.WriteLine("
    例4");
                uint ui = uint.MaxValue;
                l = (long)ui;
                Print(BitConverter.GetBytes(ui), ui.ToString(), "转化前");
                Print(BitConverter.GetBytes(l), l.ToString(), "转化后");
    
                Console.WriteLine("2、截位式转化");
    
                Console.WriteLine("
    ###64位有符号 转 32位有符号###");
                Console.WriteLine("
    例5");
                l = long.MaxValue;
                i = (int)l;
                Print(BitConverter.GetBytes(l), l.ToString(), "转化前");
                Print(BitConverter.GetBytes(i), i.ToString(), "转化后");
    
                Console.WriteLine("
    ###64位无符号 转 32位有符号###");
                Console.WriteLine("
    例6");
                ul = ulong.MaxValue;
                i = (int)ul;
                Print(BitConverter.GetBytes(ul), ul.ToString(), "转化前");
                Print(BitConverter.GetBytes(i), i.ToString(), "转化后");
    
    
                Console.WriteLine("3、转换符号位式转化");
    
                Console.WriteLine("
    ###32位无符号 转 32位有符号###");
                Console.WriteLine("
    例7");
                ui = uint.MaxValue;
                i = (int)ui;
                Print(BitConverter.GetBytes(ui), ui.ToString(), "转化前");
                Print(BitConverter.GetBytes(i), i.ToString(), "转化后");
    
                Console.WriteLine("
    ###32位有符号 转 32位无符号###");
                Console.WriteLine("
    例8");
                i = int.MinValue;
                ui = (uint)i;
                Print(BitConverter.GetBytes(i), i.ToString(), "转化前");
                Print(BitConverter.GetBytes(ui), ui.ToString(), "转化后");
    
    
                Console.Read();
            }
    
            private static void Print(byte[] buffer, string result, string tag = "")
            {
                Console.WriteLine(tag);
                Console.WriteLine("数值:" + result);
                Console.Write("字节数组(补码):");
                foreach (byte b in buffer)
                {
                    Console.Write(string.Format("{0},", b.ToString()));
                }
                Console.WriteLine("");
            }
    
        }
    

      

          

     根据上述的8个例子可以得出如下结果:

     1、补位式转化、即少位数据类型向多位数据类型转化 (例1、例2、例3、例4)

      所补位与操作数的数据类型有关,与目标数据类型无关。

      如果操作数是有符号的数据类型,所补位一律为操作数的符号位,如果操作数是无符号的数据类型,所补位一律为0。

     2、截位式转化、即多位数据类型向少位数据类型转化 (例5、例6)

      该转换方式就是简单的截取有效数位(即丢弃高位),和操作数的类型无关。

     3、转换符号位式转化、即相同位数有无符号数据类型间的转化(例7、例8)

       发生该类型转化时,只是最高位的意义发生了变化,进而可能导致结果改变。

    三、整形与浮点型间的类型转换

    有了上面的基础、再理解整形与浮点型的转换就容易多了。

    由整形向浮点型转换的时候,如果整形数据的值过大或过小,就可能损失一些最低的有效位,造成精度损失(float的精度只有7位,double15~16位)。

    四、参考资料:

    原码:http://baike.baidu.com/view/60480.htm

    补码:http://baike.baidu.com/view/377340.htm

    最后祝园友们,中秋快乐(虽然晚了,但是诚意还在吧)。

  • 相关阅读:
    转 linux下ClamAV使用
    oraagent.bin High Memory Usage as Dependent Listener was Removed/Renamed
    转 zabbix 优化方法 以及 后台数据库查询方法 两则
    转 mysql awr 报告
    转 zabbix 优化方法 以及数据库查询方法 两则
    转 检查rac服务时,发现ons服务offline
    转:HR schema
    Spring MVC初始化
    Spring MVC入门的实例
    Spring MVC 设计概述
  • 原文地址:https://www.cnblogs.com/08shiyan/p/3962423.html
Copyright © 2011-2022 走看看