.NET数字类型总结

.Net中数字类型有很多种,一直都没什么留意各种用法,因为MSDN都有很详细的介绍;最近项目中要进行许多大数字的计算和格式化、校验,下面做一些总结。

  • 范围和精度

表示小数类型有floatdoubledecimal

类型 大致范围 精度 初始化后缀
float -3.4 × 1038  +3.4 × 1038 7 f或F
double ±5.0 × 10−324  ±1.7 × 10308 15到16 d或D
decimal (-7.9 x 1028 - 7.9 x 1028) / (100 - 28) 28到29 m或M

以上是来自msdn的数据

float:http://msdn.microsoft.com/zh-cn/library/vstudio/b1e65aza.aspx
double:http://msdn.microsoft.com/zh-cn/library/vstudio/678hzkk9.aspx
decimal:http://msdn.microsoft.com/zh-cn/library/vstudio/364x0z75.aspx

解释一下“大致范围”。首先,以上数据类型都有2个常数的变量:MaxValue、MinValue,他们的值如下所示。

Console.WriteLine(float.MaxValue);      //3.402823E+38
Console.WriteLine(float.MinValue);      //-3.402823E+38
Console.WriteLine(double.MaxValue);     //1.79769313486232E+308
Console.WriteLine(double.MinValue);     //-1.79769313486232E+308
Console.WriteLine(decimal.MaxValue);    //79228162514264337593543950335
Console.WriteLine(decimal.MinValue);    //-79228162514264337593543950335

float的MaxValue和MinValue正对应表中“大致范围”的2个值。

double的MaxValue和MinValue也是对应表中的“大致范围”的2个值,那前面的±5.0 × 10−324 表示的是double的Epsilon属性。
Epsilon的解释是,表示大于零的最小正 Double 值。其实就是最接近0的数字,如果一个double值大于0且小于Epsilon,这个值会被认为跟0相等。
其实float也有Epsilon属性,值为1.4013E-045;因此个人认为,MSDN文档应该把float的“大致范围” 写成像double那样(±1.4 × 10−45 到 ±3.4 × 1038)。
PS. 这个值跟计算机平台有关系,在 ARM 系统中,值Epsilon常量太小,无法检测到,因此它相当于零,使用时要慎重。

decimal的MaxValue和MinValue看得出,全部都是数字精度一直到29位。大致范围的(-7.9 x 1028 - 7.9 x 1028) / (100 - 28),意思就是它的精度最大(小)值可以到29位。

至于这里“精度”的意思,其实是有效位数(包括整数和小数),超过有效位数的计算或显示均以四舍五入截取,其他以0显示。

float的精度为7位,由以下例子可见,不管整数还是小数加起来只显示7位。

string format = "N10";  //显示成数字,并显示10位小数
float fNumber = 1234.56789f;
Console.WriteLine(fNumber.ToString(format)); //输出1,234.5680000000
fNumber = 123456789f;
Console.WriteLine(fNumber.ToString(format)); //输出123,456,800.0000000000

double的精度为15到16位,其实就是15位有效数字,16是包含小数点的意思;javascript的number就是等价于double。
decimal的精度为28到29位,是最高精度的数字类型,适合金额、财务等计算。

计算如果涉及小数显示,在选择数字类型时,要注意精度。

  • 转换和格式化

另外,如果程序是需要在其他国家语言系统运行的,在数字的格式化方面也要有所注意。

所有基础类型,包括之前的3个小数类型,都是有:Parse的静态方法,可以支持从字符串转换到基础类型(还有TryParse);同是也有ToString格式化显示数字。

但由于国家语言、业务类型的差异,标识小数、千分位、符号表示方式、钱币符号位置等都有所差异。

打个比方,字符串"100,000",在中文、英文的语言规范中,都是代表十万这个数字;但在另一些国家语言(如法国),小数点符号为",","."才是千分号。
那这时程序如果在从字符串转换为数字类型的时候,直接如下这样写的话,结果就会出现差异,甚至出现异常。

string numberStr = "1234,567";
double number = double.Parse(numberStr);

因为double.Parse是直接使用系统的语言格式化规范,因此会出现不可预知的行为。保险期间,最好使用Parse的重载,指定IFormatProvider。

public static double Parse(string s, IFormatProvider provider);

专门有一个为数字格式化的类,实现了IFormatProvider,叫NumberFormatInfo。
在每个语言的CultureInfo实例中,都有NumberFormat属性,它是专属于那个语言的数字格式。
PS:CultureInfo包含了各种文化格式,不单止NumberFormat,还有DateTimeFormat等。格式化需要传入一个代表语言的名字或者代号,名字和代号规范请看
http://msdn.microsoft.com/zh-cn/library/system.globalization.cultureinfo(v=VS.80).aspx 。

NumberFormatInfo,有很多数字格式的属性,都跟格式化显示有关,具体请看
http://msdn.microsoft.com/zh-cn/library/system.globalization.numberformatinfo(v=VS.80).aspx

 

posted @ 2013-01-20 18:47  dct_it  阅读(2261)  评论(0编辑  收藏  举报