我们一般使用的数字型态不外乎就是int,float,double
但有关金钱的运算就需要更準确的decimal型态了
先来说一下为何不使用double呢?
大家可以试试下面这个例子
// 0.30000000000000004double a = 0.1 + 0.2;
float,double : 二进制浮点数
decimal : 十进制浮点数
会造成这个原因是因为电脑运算double会转成二进位去做运算
而小数在二进制很难完整表示,就像我们算1/3一样
所以我们需要使用更精确的decimal型态来做小数运算
// 0.3decimal b = 0.1m + 0.2m;
Tostring造成计算误差
虽然前面说数值运算要用decimal
但有时还是难免会使用到double型态
像是要计算複利时,会呼叫Math.Pow这个double funtion
//1.0221044505936159double rate = Math.pow(1.3,1.0/12.0);//1.02210445059362decimal drate = decimal.Parse(rate.Tostring());
这时发现tostring预设会四捨五入至小数点后14位
因为是在算複利,所以在几十年后会出现误差,虽然差值很小但也不容忽视
这时只要给Tostring下G17(double格式)参数就可以保留位数了
MSDN
根据预设,传回的值只包含 15 个位数的精确度虽然内部维护最多 17 个位数。 如果这个执行个体的值必须大于 15 位数,ToString会传回PositiveInfinitySymbol或NegativeInfinitySymbol而不是预期的数目。 如果您需要更多有效位数时,指定format"G17"格式规格,它一定会传回 17 个位数的有效位数或"R",它会传回 15 位数如果数目可以使用 17 位数来表示,如果只能是数字表示使用最大有效位数。
//1.0221044505936159decimal drate = decimal.Parse(rate.Tostring("G17"));
这种小数点后10几位的误差真的很难发现
但牵扯到金融相关程式
还是必须排除可能的误差