轻量级Java十进制类

时间:2008-12-09 20:05:45

标签: java decimal

我正在考虑为BigDecimal编写两个有限精度的替代品,即DecimalInt和DecimalLong。这些将能够处理int和long的实际边界内的数字以及任意数量的小数位,可以以可变形式和不可变形式创建。我的计划是使DecimalInt支持+/- 999,999,999到+/- 0.999999999和DecimalLong相同,但最多18位。

这可以通过将DecimalInt的十进制数字计数值保持为0-9,将DecimalLong的十进制数字计数值保持为0-18,并将实际值保存为缩放的int或long来实现。正常使用的是小数字小数,例如金钱和股票价格,通常是2-4位小数。

基本要求是(a)精益足迹(2个课程,加上OverflowException),以及(b)完全支持所有基本操作以及所有有意义的数学。

谷歌搜索结果没有返回任何明显的命中 - 它们似乎都属于任意小数。

我的问题是:这已经完成了吗?这有隐藏的微妙之处,这就是为什么它还没有完成?有没有人听说过Java支持像DotNet这样的十进制类型的传言。

编辑:这与BigDecimal有所不同,因为它应该是(a)不处理一组int的效率高得多,而且(b)它不会包装BigInteger所以它会更精简内存同样,(c)它会有一个可变选项,所以它也会更快。总而言之 - 对于简单的用例,例如“我想存储银行余额而没有BigDecimal的开销和双重不准确性”的开销较少。

编辑:我打算用int或long做所有数学运算来避免经典问题:1586.60-708.75 = 877.8499999999999而不是877.85

5 个答案:

答案 0 :(得分:12)

我强烈怀疑为什么没有这样做的原因是BigDecimal和BigInteger的开销并不像你想象的那么重要,并且避免它不值得努力以及以某种微妙的方式弄错它的风险。 / p>

使用你的例子:对于任何金融应用程序,保存几十个字节是一个非问题和有限精度的交易破坏者(股票价格我通常在美国2-4位数,但如果你想交易对于新兴市场,你会遇到通货膨胀失控的货币,其中15位数的货币会给你买半条面包。)

基本上,这听起来只是另一种过早优化的情况。

答案 1 :(得分:1)

大多数特别关注舍入错误的人都使用BigDecimal和BigInteger,它在大多数情况下表现都很好。

然而,在性能更为关键的情况下,使用double with rounding可以完成工作。新手经常会忘记这一点,但是如果没有明智的回合,你不能只取一个双重结果,并期望获得一个明智的答案。

在绝大多数情况下,只需要四舍五入就可以了。

System.out.printf("%.2f%n", 1586.60-708.75);

打印

877.85

答案 2 :(得分:0)

如果您专注于便携式设备,请查看Real。 Real允许将数字的precision设置为0到16.它专为MIDP手机设计。

同样有趣的是,请查看constructive reals库。但它不是轻量级的。

参考下面的评论,您是否可以使用Apache Commons Math Library处理分数?有什么理由不起作用吗?

答案 3 :(得分:0)

如果你正在寻找一个固定的,少量的小数位来处理钱,那么这通常是通过保持整数(如果必要的话很长)的分数或百分之一分来完成的。

如果您正在处理金钱,那么您需要小心如何处理四舍五入。如果要对您的计算进行审计,那么有关于如何完成此类事情的规则。另外我假设你知道某些操作不能精确地完成(除法就是明显的例子)。

答案 4 :(得分:-1)

在我看来,如果你想要任意精度,那么你将需要一个未定义的位数来表示尾数。这意味着尾数需要某种数组分配策略。你可以在这里制作你自己的,但BigInteger相当有效地完成它并且它可以工作

您需要指定需要表示的最小(非零)值。这将是10 ^ - (2 ^ n),其中n + 1是您分配给指数的位数。使用BigDecimal,这是10 ^ - (2 ^ 31)。您可以使用任意大小的指数,但该范围对任何人都应该足够。

所以你需要的是一个无界的整数尾数来给你任意精度和一个固定大小的指数,这取决于你想要的最小可表示值。基本上这是BigDecimal;唯一的变化是你将使用一些较小的对象而不是BigDecimal使用的int。我怀疑节省空间是否值得。我认为BigDecimal会用你自己制作的任何解决方案来做你需要的内存,而不是你自己制作的任何解决方案。

当然,您可以选择您需要的最大有效数字;然后你需要固定大小的存储空间用于尾数和指数,这是一个更少的存储空间。只需使用固定数量的长尾作为尾数。