【问题标题】:Add infinity math behavior to Decimal将无穷大数学行为添加到 Decimal
【发布时间】:2013-11-27 18:23:26
【问题描述】:

C# 支持二进制浮点类型(DoubleSingle)的无穷数学(请参阅:Express mathematical infinity in C#),但不支持 Decimal. 我喜欢 Decimal 类型提供的精度,但我还需要对无穷数学的支持(详情如下)。

是否有一种“懒惰”的方式来创建一个添加对 -Inf/+Inf/NaN 支持的 InfinityDecimal 结构,就像 Nullable 通用结构添加对 Nullable 类型的支持一样?也许有一些可能适用的属性的有趣用途?包含这样一个野兽的现有数学库?

否则我应该创建一个具有Decimal value 属性的类或结构,并显式实现struct Decimal 类型的每个公共方法,返回等效的Decimal 操作的结果,除非操作数是,或者结果应该是 +/-Inf 或 NaN。 对吧?

Infinity Math Operations:

+INF + N    = +INF (where –INF < N < INF)
-INF + N    = -INF (where –INF < N < INF)
+INF + +INF = +INF
-INF - +INF = -INF
+INF - +INF = NAN 
+INF * +INF = +INF
+INF * -INF = -INF
-INF * -INF = +INF
+INF / +INF = NAN
-INF / -INF = NAN
-INF / +INF = NAN
+INF / -INF = NAN
+INF / 0    = +INF
-INF / 0    = -INF
+INF / N    = +INF (where 0 < N < INF)

【问题讨论】:

  • 您是建议将其添加到 BCL 中,还是询问 如何 在 C# 中执行此操作?
  • @PeterRitchie 很明显 OP 正在寻找后者..
  • "否则我应该创建一个具有 Decimal 值属性的类或结构,并显式实现 struct Decimal 类型的每个公共方法" 是的,您需要这样做。这会很乏味,但不是特别难。
  • 怎么做。理想情况下,我希望将它添加到 BCL 中,但在短期内,我想看看是否可以通过找到现有实现或通过一些合理的捷径来实现。
  • 定义自己的类型,封装一个十进制值和一个枚举来指示该值是无穷大还是十进制值。 FWIW,十进制与精度无关。这是关于十进制表示。十进制具有有限的精度,就像双精度。但是十进制是十进制,而双精度是二进制。所以也许你应该重新考虑一下为什么你认为十进制这么好。

标签: c# generics math infinity


【解决方案1】:

如果你看看DoubleSingle 做了什么,它们基本上保留了一个值来表示正无穷和负无穷。该值基本上与每种类型中合理可能表示的正无穷大和负无穷大一样接近。通过推断,这是 1 除以非零的最小值(即Epsilon)。当然,Decimal 没有 Epsilon 属性。您可以通过创建一个非常接近零而不为零的值来创建自己的 epsilon 值:

var DecimalEpsilon = new decimal(1,0,0,false,27);

有效地0.000000000000000000000000001m

然后您可以像 Single 和 Double 一样创建正无穷和负无穷:

var DecimalPositiveInfinity =  1m / DecimalEpislon;
var DecimalNegativeInfinity = -1m / DecimalEpislon;

不幸的是,您必须自己处理 decimalValue/zeroValue 并自己包装 DivideByZeroException 并返回适当的无穷大常数——这实际上意味着包装所有除法。 NaN 也可能如此,因为这也不是 Decimal 概念(在 Single/Double 中建模为 PositiveInfinity/PositiveInfinity

Decimal 被添加到货币模型中,并尽可能提高精度以避免舍入错误和货币损失:)。在“钱”的概念中,无限没有多大意义。 :)

实现您想要的其余部分是有效的比较......

【讨论】:

  • 我不知道无穷大或非数字的概念对金钱的意义比对其他任何事物的意义都要小。结果不可表示的计算无论是抛出立即异常还是产生“哨兵”值都会造成麻烦。在许多情况下,最好让一批代码保证作为一个单元运行并在事后检查是否出现问题,而不是处理一段代码可能在中途抛出异常的可能性。即时异常可能比延迟异常更容易解决...
  • ...但是有一个ThreadStatic 对计算上下文的引用可以启用/禁用即时错误捕获或从第一次越界计算中捕获堆栈跟踪,这将使系统成为可能使两种类型的错误处理都可用于代码,具体取决于其直接需求。
  • 我期待在您的回答中看到详细信息
  • 与其使用 1/epsilon 表示无穷大,我认为直接使用 decimal.MaxValue (可能相等)更有意义,但似乎更安全。
猜你喜欢
  • 1970-01-01
  • 2022-08-12
  • 2018-05-12
  • 1970-01-01
  • 2011-08-11
  • 2018-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多