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

posted @ 2008-08-05 22:17  Birdshover  阅读(4272)  评论(4编辑  收藏  举报