谈谈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/

你可能感兴趣的:(for循环)