Npoi圆公式
Npoi Round Formula
我是 NPOI 的新手,在做项目时遇到了奇怪的问题,不知道如何解决
我正在读取来自 Excel sheet 的数据,其中包含 Round 函数并使用 npoi 评估器 XSSFFormulaEvaluator 重新评估单元格
直到这一刻之前的每一件事都对我很好,直到遇到这个问题
在 excel sheet 我有这个公式 =round(693.9648;2)
此数字的 excel 中的结果将是 693.96
但 NPOI Evaluator 的结果将是 693.97
任何人都知道我如何让评估者表现得像 excel sheet ?!
我遇到了几乎完全相同的问题。数字 481.75478 在 Excel ROUND()
函数中被用于 2dp。例如ROUND(481.75478, 2)
使用同一工作簿执行此操作时:
- Excel 的计算结果为 481.75
- NPOI 的计算结果为 481.76
这似乎与 NPOI 在 C# 中实现 Excel ROUND 函数的方式有关。最后,我下载了 NPOI 库的源代码,将 ROUND 函数更改为使用标准 .NET 舍入(使用 MidpointRounding.AwayFromZero
作为我们目的的参数)并使用我的自定义 DLL。
我downloaded the source code并做了如下修改:
文件:\main\SS\Formula\Functions\MathX.cs
原码
public static double Round(double n, int p)
{
double retval;
if (double.IsNaN(n) || double.IsInfinity(n))
{
retval = double.NaN;
}
else if (double.MaxValue == n)
return double.MaxValue;
else if (double.MinValue == n)
return 0;
else
{
if (p >= 0)
{
int temp = (int)Math.Pow(10, p);
double delta = 0.5;
int x = p + 1;
while (x > 0)
{
delta = delta / 10;
x--;
}
retval = (double)(Math.Round((decimal)(n + delta) * temp) / temp);
}
else
{
int temp = (int)Math.Pow(10, Math.Abs(p));
retval = (double)(Math.Round((decimal)(n) / temp) * temp);
}
}
return retval;
}
更新代码
public static double Round(double n, int p)
{
double retval;
if (double.IsNaN(n) || double.IsInfinity(n))
{
retval = double.NaN;
}
else if (double.MaxValue == n)
return double.MaxValue;
else if (double.MinValue == n)
return 0;
else
{
if (p >= 0)
{
// ***** updated to use .NET MidpointRounding.AwayFromZero rounding ***** //
retval = (double)Math.Round((decimal)n, p, MidpointRounding.AwayFromZero);
}
else
{
retval = (double)(Math.Round((decimal)(n) / temp) * temp);
}
}
return retval;
}
Note/Disclaimer
这还没有经过测试,所以可能会导致其他一些无法预料的错误(我不确定为什么原始代码会进行某种增量化),但这解决了我遇到的舍入不同的问题在 Excel 和 NPOI 之间。如果我在愤怒中使用该应用程序时发现任何问题,我会回来更新答案。
更新2017-12-04
这已经投入生产一段时间了,没有任何问题。我还意识到我应该为此向项目 which I now have.
提交 PR
我是 NPOI 的新手,在做项目时遇到了奇怪的问题,不知道如何解决 我正在读取来自 Excel sheet 的数据,其中包含 Round 函数并使用 npoi 评估器 XSSFFormulaEvaluator 重新评估单元格 直到这一刻之前的每一件事都对我很好,直到遇到这个问题 在 excel sheet 我有这个公式 =round(693.9648;2) 此数字的 excel 中的结果将是 693.96 但 NPOI Evaluator 的结果将是 693.97
任何人都知道我如何让评估者表现得像 excel sheet ?!
我遇到了几乎完全相同的问题。数字 481.75478 在 Excel ROUND()
函数中被用于 2dp。例如ROUND(481.75478, 2)
使用同一工作簿执行此操作时:
- Excel 的计算结果为 481.75
- NPOI 的计算结果为 481.76
这似乎与 NPOI 在 C# 中实现 Excel ROUND 函数的方式有关。最后,我下载了 NPOI 库的源代码,将 ROUND 函数更改为使用标准 .NET 舍入(使用 MidpointRounding.AwayFromZero
作为我们目的的参数)并使用我的自定义 DLL。
我downloaded the source code并做了如下修改:
文件:\main\SS\Formula\Functions\MathX.cs
原码
public static double Round(double n, int p)
{
double retval;
if (double.IsNaN(n) || double.IsInfinity(n))
{
retval = double.NaN;
}
else if (double.MaxValue == n)
return double.MaxValue;
else if (double.MinValue == n)
return 0;
else
{
if (p >= 0)
{
int temp = (int)Math.Pow(10, p);
double delta = 0.5;
int x = p + 1;
while (x > 0)
{
delta = delta / 10;
x--;
}
retval = (double)(Math.Round((decimal)(n + delta) * temp) / temp);
}
else
{
int temp = (int)Math.Pow(10, Math.Abs(p));
retval = (double)(Math.Round((decimal)(n) / temp) * temp);
}
}
return retval;
}
更新代码
public static double Round(double n, int p)
{
double retval;
if (double.IsNaN(n) || double.IsInfinity(n))
{
retval = double.NaN;
}
else if (double.MaxValue == n)
return double.MaxValue;
else if (double.MinValue == n)
return 0;
else
{
if (p >= 0)
{
// ***** updated to use .NET MidpointRounding.AwayFromZero rounding ***** //
retval = (double)Math.Round((decimal)n, p, MidpointRounding.AwayFromZero);
}
else
{
retval = (double)(Math.Round((decimal)(n) / temp) * temp);
}
}
return retval;
}
Note/Disclaimer
这还没有经过测试,所以可能会导致其他一些无法预料的错误(我不确定为什么原始代码会进行某种增量化),但这解决了我遇到的舍入不同的问题在 Excel 和 NPOI 之间。如果我在愤怒中使用该应用程序时发现任何问题,我会回来更新答案。
更新2017-12-04
这已经投入生产一段时间了,没有任何问题。我还意识到我应该为此向项目 which I now have.
提交 PR