代码之家  ›  专栏  ›  技术社区  ›  L. Cornelius Dol

轻量级Java十进制类

  •  12
  • L. Cornelius Dol  · 技术社区  · 17 年前

    我正在考虑写两个有限精度的BigDecimal替代品,即DecimalInt和DecimalLong。这些函数能够处理int和long的实数范围内的任意小数位数的数字,这些数字可以以可变和不可变的形式创建。我的计划是让十进制支持从+/-999999999到+/-0.999999999和十进制支持相同,但最多支持18位数字。

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

    搜索结果并没有返回任何明显的点击-它们似乎都与任意小数有关。

    编辑:这与BigDecimal不同,因为它应该(a)更高效地不处理一个int数组,并且(b)它不会包装BigInteger,所以它也会更节省内存,并且(c)它有一个可变选项,所以在那里也会更快。总之,对于简单的用例,比如“我想存储一个银行余额,而不需要BigDecimal的开销和double的不精确性”。

    编辑:我打算使用int或long来完成所有的数学运算,以避免经典问题:1586.60-708.75=877.84999999999而不是877.85

    5 回复  |  直到 15 年前
        1
  •  13
  •   Michael Borgwardt    17 年前

    我强烈怀疑没有这样做的原因是BigDecimal和BigInteger的开销没有您想象的那么相关,并且避免它不值得付出努力,并且有可能以某种微妙的方式出错。

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

    基本上,这听起来只是另一个过早优化的例子。

        2
  •  1
  •   Peter Lawrey    15 年前

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

    但是,在性能更为关键的情况下,使用带舍入的double可以完成工作。新手们常常会忘记这一点,但如果没有明智的选择,你就不能指望得到明智的答案。

    在绝大多数情况下,双倍取整是你所需要的。

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

    印刷品

    877.85
    
        3
  •  0
  •   DJClayworth    17 年前

    如果你看的是一个固定的小数位来处理钱,那么这通常是通过保持整数(如果有必要的话长)的美分数,或者百分之一美分来完成的。

        4
  •  0
  •   WolfmanDragon    17 年前

    如果你的焦点是便携式设备,请看 Real . 真的允许 precision 从0到16的数字。它是为MIDP手机设计的。

    同样有趣的是,看看 constructive reals 图书馆。不过,它并不轻。

    Apache Commons Math Library 和分数一起工作?有没有什么不起作用的原因?

        5
  •  -1
  •   DJClayworth    17 年前

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

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

    所以你需要一个无界的整数尾数来给你任意的精度,一个固定大小的指数,这取决于你想要你的最小可表示值是什么。本质上这是BigDecimal;唯一的变化是您将使用一些较小的对象,而不是BigDecimal使用的int。我怀疑节省的空间是否值得。我认为BigDecimal只需要比你自己设计的任何解决方案占用更多的内存就可以满足你的需要。

    当然,您可以选择您需要的最大数量的重要图形;然后您需要尾数和指数的固定大小的存储,这是一个更少的存储空间。只要用固定数量的长线作为尾数。