c#中decimal ,double,float的区别

转自:http://www.cnblogs.com/lovewife/articles/2466543.html

单精度就是指4个字节的浮点数,即float
双精度就是指8个字节的浮点数,即double

decimal是高精度

浮点型


Name


CTS Type


Description


Significant Figures


Range (approximate)


float


System.Single


32-bit single-precision floating point


7


±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。

还有两个非常危险的错误认识!!

1、decimal不是浮点型、decimal不存在精度损失。

下面有段程序大家可以去看看结果是什么。记住!所有的浮点型变量都存在精度损失的问题,而decimal是一个不折不扣的浮点型,不论它精度有多高,精度损失依然存在!

decimal dd = 10000000000000000000000000000m;

dd += 0.1m;

Console.WriteLine ( "{0:G50}", dd );

2、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 了。

时间: 2024-08-21 14:21:12

c#中decimal ,double,float的区别的相关文章

decimal, double, float

refers : http://blog.leanote.com/post/weibo-007/mysql_float_double_decimal https://brooch.me/2016/11/17/%E6%B5%AE%E7%82%B9%E6%95%B0%E8%AE%A1%E7%AE%97%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B8%8D%E7%B2%BE%E7%A1%AE/ https://frontstuff.io/how-to-handle-monetary-

MySQL中 DECIMAL FLOAT DOUBLE的区别

第一篇文章: MySQL中Decimal类型和Float Double等区别 MySQL中存在float,double等非标准数据类型,也有decimal这种标准数据类型. 其区别在于,float,double等非标准类型,在DB中保存的是近似值,而Decimal则以字符串的形式保存数值.float,double类型是可以存浮点数(即小数类型),但是float有个坏处,当你给定的数据是整数的时候,那么它就以整数给你处理.这样我们在存取货币值的时候自然遇到问题,我的default值为:0.00而实

Java中浮点类型的精度问题 double float

要说清楚Java浮点数的取值范围与其精度,必须先了解浮点数的表示方法与浮点数的结构组成.因为机器只认识01,你想表示小数,你要机器认识小数点这个东西,必须采用某种方法.比如,简单点的,float四个字节,前两个字节表示整数位,后两个字节表示小数位(这就是一种规则标准),这样就组成一个浮点数.而Java中浮点数采用的是IEEE 754标准. IEEE 754 标准 更多详见:https://baike.baidu.com/item/IEEE%20754 IEEE 754 标准是IEEE二进位浮点数

C#中堆和栈的区别分析

线程堆栈:简称栈 Stack托管堆: 简称堆 Heap 使用.Net框架开发程序的时候,我们无需关心内存分配问题,因为有GC这个大管家给我们料理一切.如果我们写出如下两段代码: 1 代码段1: 2 3 public int AddFive(int pValue) 4 { 5 int result; 6 result = pValue + 5; 7 return result; 8 } 1 代码段2: 2 3 public class MyInt 4 { 5 public int MyValue;

浅谈C#中堆和栈的区别(附上图解)

线程堆栈:简称栈 Stack 托管堆: 简称堆 Heap 使用.Net框架开发程序的时候,我们无需关心内存分配问题,因为有GC这个大管家给我们料理一切.如果我们写出如下两段代码: 代码段1: public int AddFive(int pValue) { int result; result = pValue + 5; return result; } 代码段2: public class MyInt { public int MyValue; } public MyInt AddFive(i

.NET中struct与class的区别

在.net中的struct与class有很多相似之处,比如可以直接new,对于成员可以直接XX.field,以至于有不少程序员在用时,将其混在一起,分不清有何区别.这两者有何区别呢? 1.类型不同 我们先来看一段代码 static void Main(string[] args) { TypeDemo(); Console.ReadLine(); } // Reference type (because of 'class') class SomeClassRef { public Int32

C#中ref和out的区别浅析

这篇文章主要介绍了C#中ref和out的区别浅析,当一个方法需要返回多个值的时候,就需要用到ref和out,那么这两个方法区别在哪儿呢,需要的朋友可以参考下 在C#中通过使用方法来获取返回值时,通常只能得到一个返回值.因此,当一个方法需要返回多个值的时候,就需要用到ref和out,那么这两个方法区别在哪儿呢? MSDN:       ref 关键字使参数按引用传递.其效果是,当控制权传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中.若要使用 ref 参数,则方法定义和调用方法都必

转载:C#中ref和out的区别浅析

这篇文章主要介绍了C#中ref和out的区别浅析,当一个方法需要返回多个值的时候,就需要用到ref和out,那么这两个方法区别在哪儿呢,需要的朋友可以参考下 在C#中通过使用方法来获取返回值时,通常只能得到一个返回值.因此,当一个方法需要返回多个值的时候,就需要用到ref和out,那么这两个方法区别在哪儿呢? MSDN:        ref 关键字使参数按引用传递.其效果是,当控制权传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中.若要使用 ref 参数,则方法定义和调用方法都

SQL Server 中CAST和Convert的区别

在 SQL Server 中Cast和Convert都是将表达式由一种数据类型转换为另一种数据类型.由于SQL Server提供两种功能,因此应该选择哪种功能或应该在哪种情况下使用该功能就很容易让人困惑了.CONVERT是专对SQL Server使用的,使日期与时间值,小数之间转换具有更宽的灵活性.CAST是两种功能中更具ANSI标准的功能,即虽然更具便携性(比如,使用CAST的函数能更容易的被其它数据库软件使用),但功能相对弱一些.不过,当小数转化为数值,并保留原始表达式中的小数数值时,仍然需