Math.Round() 同时转换和计算返回错误的结果

Posted

技术标签:

【中文标题】Math.Round() 同时转换和计算返回错误的结果【英文标题】:Math.Round() while casting and calculating returning wrong result 【发布时间】:2018-09-07 12:59:00 【问题描述】:

我只是想知道是否有人可以向我解释为什么这些不同的数据类型在我的代码中舍入不同? (注意:这不是变量的实际声明方式,而是它们的存储方式。为了清楚起见,我只是这样显示它们)

double amount = 15 ;
double taxPercentage = 0.015;
decimal itemTax;

首先,未四舍五入的结果:

itemTax = (decimal)(amount * taxPercentage);
  // itemTax returns -0.225

如果我先四舍五入,然后转换为小数:

itemTax = (decimal)(Math.Round(amount * taxPercentage, 2, MidpointRounding.AwayFromZero));
  // itemTax returns -0.22 

如果我先转换为十进制,然后四舍五入:

itemTax = (decimal)(amount * taxPercentage);
itemTax = Math.Round(itemTax,2,MidpointRounding.AwayFromZero);
 //  itemTax returns -0.23

这是否与双精度类型与十进制类型的舍入方式有关?

【问题讨论】:

你应该包括amounttaxPercentage的分配 换句话说,当我使用100-.00025 时,这不会为我复制。但是双精度和小数肯定有不同的精度。此外,除非您转换为小数,否则您的第一个样本(“未舍入”结果)不会编译。 $" amount * taxPercentage : G20" 打印出什么?还有$" (decimal)(amount * taxPercentage) : G20"?发现有什么不同吗? 另外,您应该完全避免这个问题。 decimal 的语言正好用于需要精确计算的财务计算。不要在涉及金钱时使用double,因为这种不愉快的事情往往会出现。 C# double to decimal precision loss的可能重复 【参考方案1】:

的确如此。 Double(如 float)是以 2 为底的数字,实际上是十进制值的近似值。与十进制值不同,它不能表示无限精度数字,因此您的 -0.025 值可能实际上是 -0.024999999999

【讨论】:

以上是关于Math.Round() 同时转换和计算返回错误的结果的主要内容,如果未能解决你的问题,请参考以下文章

js使用Math.round() 精确保留小数点后几位,同时小数为0的省略

js中Math.roundparseIntMath.floor和Math.ceil小数取整总结

Math对象(min()-max()-ceil()-floor()-round()和abs())

C#中Math类的计算整数的三种方法

java中"(double)(Math.round(x3 * 10000))/10000"为啥这个东西会输出小数啊?

Math中的floor,round和ceil方法总结