zoukankan      html  css  js  c++  java
  • 谈谈C#的数值类型——顺便给for循环做个补充

    补充一下:上次讲for循环的文章 详解for循环(各种用法)

    假如变量的值 i = int.MaxValue;这个时候运行;Console.WriteLine(++i);输出什么?

    假如我的循环写成这样:

               int start = int.MaxValue - 10;
                
    int max = int.MaxValue;
                
    for (int i = start; i < max + 100; i++)
                {
                    Console.WriteLine(i);
                }

    又会输出什么?

    答案令人大跌眼镜。

                int i = int.MaxValue;
                Console.WriteLine(
    int.MaxValue);
                i
    ++;
                Console.WriteLine(i);

    输出了

    2147483647

    -2147483648

    而上面的循环,编译正确,却没有被执行。为什么没有被执行?推断一下,int的最大值+1是负数,那么+100估计(嘿嘿,这里带有估计的一种情感)也是负数。那么i是int最大值减去10,是个正数,怎么也不能小于负数不是?那就不执行了。果然,int.MaxValue+100 = -2147483549。

    为啥会这样?这就要从数字的补码说起了。你也猜到了吧?呵呵,-2147483648就是2147483647的补码嘛!

    2147483647  的16进制是 0x7FFFFFFF ,2进制就是32个1,

    而-2147483648 的16进制就是0x80000000,2进制就是1和32个0。

    看出来啦,C#内部并没有对int做溢出运算。加个checked就搞定了。

                int i = int.MaxValue;
                
    checked
                {
                    i
    ++;
                }

    这个时候就会抛出一个异常。但是,一般还是少抛出异常的好,自己动手检查一下就好了。

    再回到循环,要是溢出,会对循环产生什么影响呢?把上面的循环改成:

                int start = int.MaxValue - 10;
                
    int max = int.MaxValue;
                
    for (int i = start; i <= int.MaxValue; i++)
                {
                    Console.WriteLine(i);
                }

    输出什么呢? 成无限循环了!!!

    在int中可能不太会出现这种问题,在byte里就会有这种状况。

                for (byte i = 0; i <= 255; i++)
                {
                    Console.WriteLine(i);
                }

    在上面的情况中,可能就想对byte的各种取值进行处理而已,但是,现在办不到了,因为这个循环成无限循环了。以下代码就可以解决这种状况:

        class Program
        {

            
    static void Main(string[] args)
            {
                
    for (byte i = 0; IsMax(ref i); )
                {
                    Console.WriteLine(i);
                }
                Console.Read();
            }

            
    static bool IsMax(ref byte i)
            {
                
    if (i == 255)
                    
    return false;
                
    else
                {
                    i
    ++;
                    
    return true;
                }
            }
        }

    这是比较特殊的解决方案。事实上还有其他运算来保证不溢出。

    就是用&运算。比如:

                int i = int.MaxValue;
                i 
    = (i = i + 2& 0x7FFFFFFF;
                Console.WriteLine(i);

    这段代码,输出的结果就是1.有兴趣的朋友可以自己做2进制的与运算看看,0x7FFFFFFF就是int的最大值的16进制的表达方式。

    这种用法看似没有用。

    但下面的代码中就能有效避免错误了,呵呵

        class Program
        {
            
    static string[] s = new string[128];

            
    static void Main(string[] args)
            {
                
    byte b = 129;
                setValue((
    sbyte)b, "asdasd");
                Console.WriteLine(getValue((
    sbyte)b));
                Console.Read();
            }

            
    static string getValue(sbyte b)
            {
                
    return s[b & 0x7F];
            }

            
    static void setValue(sbyte b, string value)
            {
                s[b 
    & 0x7F= value;
            }
        }

    最后讲最后一种数据类型,其他的都和上面三种类似,但是最后一种是个特例。

    看看这句代码

                decimal d = decimal.MaxValue;
                Console.WriteLine(++d);

    这个会输出什么呢?自己去试试吧,呵呵。

    看了以上的代码对你也许没什么用,起一个警惕作用也是不错的。至于下面点的与操作,可能会对你看别人写的代码有所帮助。

    这篇文章讲的比较简单,不过要完全理解,我是说深刻理解数据类型,不是我这个文章,还是需要了解很多方面的东西的。这种可以说是程序员的内功,不但要去学OOP,OOD,SOA等等设计上的东西,对底层还是要多学一学,设计的那是招式,内功还是要多练练的。练好内功有助于写出稳定的代码,架构再好,程序也需要稳定不是吗?

    2008年8月5日 by yurow @ http://www.cnblogs.com/birdshover/

  • 相关阅读:
    【数论】 快速幂
    【时间复杂度】你还在担心时间复杂度太高吗?
    【数据结构】 最小生成树(三)——prim算法
    【数据结构】 最小生成树(二)——kruskal算法
    node.js初识11
    node.js初识10
    node.js初识09
    node.js初识08
    node.js初识07
    node.js初识06
  • 原文地址:https://www.cnblogs.com/birdshover/p/1261502.html
Copyright © 2011-2022 走看看