【问题标题】:Java precise calculations - options to useJava 精确计算 - 使用选项
【发布时间】:2013-04-26 10:23:29
【问题描述】:

我正在尝试对我们在 JAVA+SQL 中有哪些用于精确计算的选项进行简要概述。到目前为止,我找到了以下选项:

  1. 接受他们的缺点使用双打,不行。
  2. 使用 BigDecimals
    • 在复杂的公式中使用它们对我来说是个问题
  3. 使用 String.format/Decimal.format 舍入双精度数
    • 我需要对公式中的每个变量进行舍入还是只对结果进行舍入以获得 BigDecimal 精度?
    • 如何调整?
  4. 在 SQL 中使用计算字段选项。
    • 缺点是我需要动态 SQL 从不同的表中提取数据 + 计算其他计算字段上的字段,这会变得混乱

还有其他选择吗?

问题陈述: 我需要精确的财务计算,这将涉及使用非常大(十亿)和非常小的数字(0.0000004321),并且还要划分彼此非常相似的值,所以我肯定需要 BigDecimal 的精度。

另一方面,我想保留双精度在函数中的易用性(我处理来自十进制 SQL 数据的数组),因此计算如下:(a[i] - b[i])/b[i ] 等等等等,这些都在其他计算中进一步使用。我希望用户能够根据需要设计自己的公式(使用常见的数学语句)

我热衷于对 String.format 使用“格式化”解决方案,但这使得代码的可读性不强(对每个变量使用 String.format()...)。

非常感谢关于如何处理这些东西的建议。

【问题讨论】:

  • 这可能会有所帮助...stackoverflow.com/questions/8636228/…
  • 你的需求被设计破坏了,回到分析阶段。如果您没有固定的、强制性的和详尽的定义何时以及如何应用舍入,则任何财务数据都会被第一个或第二个使用它的人视为计算错误

标签: java double precision bigdecimal formulas


【解决方案1】:

您无法避免 floatdouble 中的浮点错误。 这里没有免费的奶酪 - 使用 BigDecimal。

【讨论】:

  • @Eugene,好的,谢谢你的评论,但是让我们挑战 BigDecimals。要使下面的示例代码正常工作需要什么? // 我知道这不是正确的语法,但我想这样 ;) BigDecimal a = 1234.59053232; BigDecimal b = 1.000054530;大十进制 c; c = a/b; //或任何其他具有“人类”友好语法的公式?并在输出上获得准确的 c 值,假设精度为 4 位?
  • @mtx 您可以在 BigDecimal 上“隐藏”此操作。常见的数学语句可以映射到 ENUM,并提供诸如:DIVIDE、SQUARE 等操作。您不能在非人类 BigDecimal 类型上使用人类语法。同样在您的特定示例中,除法操作看起来像这样 a.divide(b,4,RoundingMode.HALF_UP)
【解决方案2】:

来自Effective Java(第二版):

第 48 条:如果需要准确答案,请避免使用 float 和 double

  • Float 和 double 不能提供精确的结果,不应在需要精确结果的地方使用。 float 和 double 类型特别不适合货币计算,因为不可能将 0.1(或任何其他 10 的负幂)表示为 float 或 double。

  • 解决此问题的正确方法是使用 BigDecimal、int 或 long 进行货币计算。

...

另一种方法是使用 int 或 long 并自己跟踪小数点。

【讨论】:

    【解决方案3】:

    没有办法在double 上获得BigDecimal 的精度。 doubles 具有双精度。

    如果您想保证精确的结果,请使用BigDecimal

    可以创建自己的变体,使用 long 存储整数部分和 int 存储小数部分 - 但为什么要重新发明轮子。

    任何时候都可以使用doubles 来解决双精度问题。如果你在一个地方使用它们,你还不如在任何地方使用它们。

    即使您只使用它们来表示数据库中的数据,也会将数据四舍五入为双精度,您将丢失信息。

    【讨论】:

      【解决方案4】:

      如果我理解您的问题,您希望使用比原生 Java 更精确的数据类型,而不会丢失简单的数学语法(例如 / + * - 等等)。由于您不能在 Java 中重载运算符,我认为这是不可能的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-11-26
        • 2013-10-02
        • 2016-12-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多