【问题标题】:Is there a Math API for Pow(decimal, decimal)是否有 Pow 的数学 API(十进制,十进制)
【发布时间】:2011-09-19 12:14:23
【问题描述】:

是否有用于十进制计算的库,尤其是Pow(decimal, decimal) 方法?我找不到。

它可以是免费的,也可以是商业的,无论哪种方式,只要有一个。

注意:我自己不能做,不能用for循环,不能用Math.PowMath.ExpMath.Log,因为他们都取doubles,我不能使用doubles。我不能使用系列,因为它会像 doubles 一样精确。

【问题讨论】:

  • 为什么不能使用双打?尝试使用 ILSpy 或 Reflector 并从 Math.Pow 获取代码并根据需要修改它以使用十进制。
  • 有一些奇怪的要求。是什么阻止你写一篇文章?
  • 这可能会有所帮助:Raising a decimal to a power of decimal ?
  • 乘数之一是比率:1 / someOtherDecimalRate^(nbDays/365)。
  • @Maxime:你会在那里失去精度。小数是十进制数,365 的小数不能完全以 10 为基数表示,所以nbDays/365 的结果已经不精确了。

标签: c# .net math decimal


【解决方案1】:

其中一个乘数是比率:1/rate^(days/365)。

没有十进制幂函数的原因是因为使用decimal 进行计算是没有意义的。使用double

请记住,小数点是为了确保您对可以完全表示为十进制数字的值进行精确的算术运算。对于ratedays 的合理值,任何其他子表达式的值显然不会精确地表示为短十进制值。您将要处理不精确的值,因此请使用专为快速计算稍微不精确的值而设计的类型,例如 double。

以双精度计算的结果会以某种方式偏离十亿分之一美分。谁在乎? 您稍后会解决该错误。以双倍计算费率。一旦你有一个结果需要再次转换为货币,将结果乘以一万,四舍五入到最接近的整数,将其转换为小数,然后再除以一万,你'将得到精确到小数点后四位的结果,这对于财务计算来说应该足够了。

【讨论】:

  • decimal 不提供更高的精度吗?它获得的 64 个额外位必须有所帮助......
  • @configurator:您的问题的答案是“是”。您在问题之后的陈述与问题的答案不合逻辑。为什么双倍的比特数有助于解决金融问题,比如精确到十分之一便士?显然,问题是关于每日复利计算的;在计算今天的利息时,是否存在需要超过 15 个小数位精度的复合日常银行业务问题?如果今天的利息是双倍的 10.92857924858 美元和十进制的 10.9285792485820968039468095 美元,这有关系吗?
  • 当我处理复合日常兴趣时,我们被要求精确到小数点后 12 位,我个人认为这很危险地接近 double 的极限。 (没关系,这 12 位数字是完全任意的,“准确”意味着“与有严重缺陷的旧 VB3 实现相同的值”,所以我们需要引入计算错误......)
  • @configurator:哇,听起来很有趣。我无论如何都不是数值方法方面的专家,但我在职业生涯的早期做了相当多的研究和一些专业工作,根据我的经验,除非偏微分方程中有一些“刚度”,否则你'重新求解,不需要精确到十二个位置。十二位数的要求是否有一些基于数值方法的理由?
  • @colmde:正是我的观点。通过四舍五入,您是说您愿意承担比计算过程引起的误差大很多很多数量级的错误。如果在引入 small 错误之后,large 舍入引入了太多错误,那么您一开始就不应该进行大舍入。
【解决方案2】:

这是我使用的。

output = (decimal)Math.Pow((double)var1, (double)var2);

现在我只是在学习,但这确实有效,但我不知道我是否能正确解释。

我相信这样做是获取 var1 和 var2 的输入并将它们转换为双精度值,以用作 math.pow 方法的参数。之后,在 math.pow 前面有 (decimal) 将值恢复为小数并将值放在输出变量中。

如果我的解释有误,我希望有人能纠正我,但我只知道它对我有用。

【讨论】:

  • 这也是我经常做的事情 ;)
  • 是的,我这样做了,直到结果超出小数范围,最终出现溢出异常
【解决方案3】:

嗯,这里是列出当前 C# 数字库的 Wikipedia 页面。但是 TBH 我认为对小数的支持并不多

http://en.wikipedia.org/wiki/List_of_numerical_libraries

一般来说,在这种计算中使用小数是不合适的。是的,它是高精度的——但它也是低范围的。正如 MSDN 文档所述,它用于财务/货币计算 - 不幸的是,没有太多需要 POW 的地方!

当然,您可能有一个需要超高精度的特定问题域,并且所有数字都在 10(28) - 10(-28) 之间。但在这种情况下,您可能只需要编写自己的系列计算器,例如问题的 cmets 中链接到的系列计算器。

【讨论】:

  • OP后来提到他正在使用Decimals,因为他正在使用金钱。在这种情况下,我认为他最好关注Eric Lippert's advice
  • 很公平 - 他正在做财务计算的事实是后来添加的。显然,不需要他所说的财务计算的准确性。
  • 这不是真的。 Pow 用于计算几何平均值等,用于计算 FT30 指数、FPIJ 通胀指数等。说“我不知道任何情况”比声称根本没有使用要诚实得多。
  • 哇 - 9 年前 - 过去的爆炸。只是重新阅读帖子,我看不到任何我声称“根本没有使用它”的地方。我只是说没有太多要求 - 这是真的。但是感谢您的评论。
【解决方案4】:

我知道这是一个旧线程,但我将其放在这里以防有人在搜索解决方案时发现它。 如果您不想搞乱转换和自己的自定义实现,您可以安装 NuGet DecimalMath.DecimalEx 并像 DecimalEx.Pow(number,power) 一样使用它。

【讨论】:

    【解决方案5】:

    不使用decimal。请改用double。根据这个线程,Math.Pow(double, double) 是直接从 CLR 调用的。

    How is Math.Pow() implemented in .NET Framework?

    这是 .NET Framework 4 的功能(仅 2 行)

    [SecuritySafeCritical]
    public static extern double Pow(double x, double y);
    

    64 位十进制在这个 32 位 CLR 中还不是原生的。也许将来会在 64 位框架上?

    【讨论】:

      【解决方案6】:

      等等,嗯?为什么你不能使用双打?如果您使用整数或其他东西,您总是可以转换:

      int a = 1;
      int b = 2;
      int result = (int)Math.Pow(a,b);
      

      【讨论】:

      • 我认为这里的重点是获得比双精度更高的精度...否则为什么要使用小数呢?
      • 您同样可以将此答案改写为“Decimal 类型的意义何在?”
      • 我玩的是钱,显然我不会用整数。
      猜你喜欢
      • 1970-01-01
      • 2014-05-10
      • 1970-01-01
      • 2013-01-15
      • 1970-01-01
      • 2011-12-09
      • 2019-03-02
      • 2020-02-09
      • 2018-01-19
      相关资源
      最近更新 更多