浮点型安全
Nameapp |
CTS Type性能 |
Description测试 |
Significant Figuresblog |
Range (approximate)ip |
---|---|---|---|---|
floatci |
System.Singleget |
32-bit single-precision floating point编译器 |
7it |
±1.5 × 10?45 to ±3.4 × 1038 |
double |
System.Double |
64-bit double-precision floating point |
15/16 |
±5.0 × 10 ?324 to ±1.7 × 10308 |
若是咱们在代码中写一个12.3,编译器会自动认为这个数是个double型。因此若是咱们想指定12.3为float类型,那么你必须在数字后面加上F/f:
float f = 12.3F;
decimal类型
做为补充,decimal类型用来表示高精度的浮点数
Name |
CTS Type |
Description |
Significant Figures |
Range (approximate) |
---|---|---|---|---|
decimal |
System.Decimal |
128-bit high precision decimal notation |
28 |
±1.0 × 10?28 to ±7.9 × 1028 |
从上表能够看出,decimal的有效位数很大,达到了28位,可是表示的数据范围却比float和double类型小。decimal类型并非C#中的基础类型,因此使用的时候会对计算时的性能有影响。
咱们能够像以下的方式定义一个decimal类型的浮点数:
decimal d = 12.30M;
对decimal、float、double错误的认识
在精确计算中使用浮点数是很是危险的,尽管C#在浮点数运算时采起了不少措施使得浮点数运算的结果看起来是很是正常的。但实际上若是不清楚浮点数的特性而贸然使用的话,将形成很是严重的隐患。
考虑下面的语句:
double dd = 10000000000000000000000d;
dd += 1;
Console.WriteLine ( "{0:G50}", dd );
输出是什么?谁知道?
输出是:1000000000000000000000000
这就是浮点数精度损失的问题,最重要的是,在精度损失的时候,不会报告任何的错误,也不会有任何的异常产生。
浮点数的精度损失可能在不少地方出现,例如d * g / g 不必定等于d,d / g * g也不必定等于d。
还有两个很是危险的错误认识!!
一、decimal不是浮点型、decimal不存在精度损失。
下面有段程序你们能够去看看结果是什么。记住!全部的浮点型变量都存在精度损失的问题,而decimal是一个彻彻底底的浮点型,不论它精度有多高,精度损失依然存在!
decimal dd = 10000000000000000000000000000m;
dd += 0.1m;
Console.WriteLine ( "{0:G50}", dd );
二、decimal所能储存的数比double大,从double到decimal的类型转换不会出现任何问题。
微软在decimal的帮助上真的要好好检讨了。实际上只有从整形到decimal的转换才是扩大转换,decimal的精度比double大,但所能储存的最大数却比double要小。
“decimal 类型是适合财务和货币计算的 128 位数据类型。”
固然,decimal在大多数状况下是安全的,但浮点数在理论上是不安全的。
至于精度偏差形成的显示问题,则是很容易修补的。浮点数会带来的问题以及整型能避免的问题就是一个:
譬如说从A账户转帐到B账户,经计算得出结果是3.788888888888888元,那么咱们从A账户扣除这么多钱,B账户增长这么多钱,但事实上A账户不必定会扣除准确的数值,例如A账户的金额在100000000000,那么这个时候100000000000 - 3.788888888888888运算结果颇有多是99999999996.211111111111112。而这个时候B账户的金额为0则颇有可能加上准确的数值,如3.788888888888888,这样一来,0.011111111111112元钱就会不见了,日积月累的,差额就会愈来愈大。
double是64位的,比single-32位精度高
decimal128位高精度浮点数,经常使用于金融运算,不会出现浮点数计算的偏差
,decimal 类型具备更高的精度和更小的范围,这使它适合于财务和货币计算。
早上刚到办公室,就被中试室打来电话叫去,原来软件在测试过程当中发现了个小问题:软件读出来的数据比设备LCD上显示数据小了 0.01 。
怎么会这样呢,数据类型我已经用了 double 型了整个数据长度也就6位,double型的数据有效数据位为7位,也够了阿,不明白。因而回来下断点跟踪。
前面double型在算的时候,是没问题的,数据是66.24,但是当我把66.24 乘上100后的处理结果就不对了:66.24*100.0d = 6623.9999…91,问题就出在这里了。查了msdn,Double型的数据:Double 值类型表示一个值介于 -1.79769313486232e308 和 +1.79769313486232e308 之间的双精度 64 位数字,浮点数只能近似于十进制数字,浮点数的精度决定了浮点数近似于十进制数字的精确程度。默认状况下,Double 值的精度是 15 个十进制位,但内部维护的最大精度是 17 位。因此就出现了乘上一百后,精度就不够了。又因为咱们在处理数据时,是不容许四舍五入的,因此,通过单位转换后,软件中最终显示的数据为 66.23 ,比LCD上显示的66.24 小了 0.01。
所以,这以后就想到了应该用更高精度的 decimal 型。
类型 |
大体范围 |
精度 |
.NET Framework 类型 |
decimal |
±1.0 × 10e?28 至 ±7.9 × 10e28 |
28 到 29 位有效位 |
System.Decimal |
在声明decimal类型数据时,能够 a: decimal myData = 100,此时编译器隐式转换整型数100为 100.0m;固然也能够b: decimal myData = 100.0m,可是 若是是 decimal myData = 100.0d或者decimal myData = 100.0f,就不行了,由于100.0d或者100.0f,编译器认为是浮点数,而浮点数和decimal 类型之间不存在隐式转换;所以,必须使用强制转换在这两种类型之间进行转换。This is the important,不然编译器便报错。因此通常的财务软件在处理时,都会用decimal 类型。
好了,改用decimal 型以后,就OK 了,结果就完完整整地显示为 66.24 了。
来源:http://lj.soft.blog.163.com/blog/static/79402481201032210173381/