0

我需要编写一个小型 Java 程序来处理涉及金钱的计算。因此,它需要具有准确性。(例如:没有float/double变量,只有long)。

不幸的是,我需要使用的原始值是通过一种只能将变量读取为“double”的方法导入的。

现在,我尝试long使用类似于以下的方法将其转换为:

double importedValue = x;
double importedValueConverted = (long) x;

但是,当我尝试将 importValueConverted 除以另一个“长”变量时,我得到:

必需:长期发现:双重错误:可能丢失精度

这是为什么?

4

6 回答 6

3
double importedValue = x;
double importedValueConverted = (long) x;

请注意,这两个变量都被声明为“double”。这会导致您的错误(释义):(您正在执行的操作需要 a)long(但是当它尝试时发现 a)double

你要:

double importedValue = x;
long importedValueConverted = (long) x;
于 2012-09-28T18:11:01.580 回答
2

忘记所有的铸造业务。如果您正在处理财务计算,您可以直接使用 BigDecimal 包装所谓的方法返回的双精度数,并使用 BigDecimal 提供的适合您需要的适当舍入机制。

于 2012-09-28T20:06:30.573 回答
1

更新:

这篇文章提出了一个我认为从未得到回答的额外问题——为什么使用int,或者更好,long或者BigDecimal用于货币计算。这是在这里回答的:

为什么不使用 double 或 float 来表示货币(或需要任何精确计算的地方)?

因为浮点数和双精度数不能准确地表示大多数以 10 为底的实数。

即使在使用时BigDecimal,也必须使用String构造函数而不是构造函数float

综上所述,您最好的选择是:

  • 将所有值转换为美分并存储为long(将每个美元金额乘以 100)
  • 以美分进行操作
  • 最后除以 100 转换回美元

这将保持所需的精度。显然,这个解决方案考虑到了美元,任何外币兑换都需要适当考虑。


long考虑四舍五入到最接近的值,而不是强制转换:

double d = 1234.56;
long x = Math.round(d);

我真的问你为什么要从 adouble转到 a long,因为这会让你失去十进制值的精度。

如果你想保持一些精度(比如最多 3 位),并且你绝对只能使用 long来做到这一点,你可以将两个双精度数乘以 1,000,然后将所有后续操作缩放相同的因子,然后缩放它们全部回到最后,就像这样:

double starting = 1234.5678;
double worker = starting * 1000;
long roundedWorker = Math.round(worker);

// do other computations here...
// due to earlier scaling, adding 1000 is equivalent to adding 1 to the original
long longResult = roundedWorker + 1000;

double threeDigitPreciseResult = longResult / 1000d;
System.out.println("Adding 1 to original number as a long: " + threeDigitPreciseResult);

更新

在对问题进行了更好的解释之后,听起来您正在寻找的是DecimalFormat. 下面是一个roundToTwoDecimals()使用它的方法,以及一个演示它的测试用例:

import java.text.DecimalFormat;

import org.junit.Test;

public class ExampleTest {
  @Test
  public void test() {
    double num1 = 29334.32942032432;
    double num2 = 438.95940;
    double result = num1 / num2;
    System.out.println("Before rounding: " + result);

    double rounded = roundToTwoDecimals(result);
    System.out.println("After rounding: " + rounded);
  }

  public double roundToTwoDecimals(double d) {
    DecimalFormat twoDForm = new DecimalFormat("#.##");
    return Double.valueOf(twoDForm.format(d));
  }

}

打印出来:

Before rounding: 66.82697629968585
After rounding: 66.83
于 2012-09-28T18:53:35.350 回答
0

为什么不看看BigDecimal。当我使用它时效果很好。使用 Double ctor 时要小心,因为 Double 不是那么精确(例如,它不能准确地存储 0.1)。将String ctor 用于 BigDecimal可能更有用

于 2012-09-28T18:39:42.290 回答
0

如果你想投双倍长,你可以在下面做。

    double importedValue = 8.0;
    long importedValueConverted = (long) 8.0;
    System.out.println(importedValueConverted/(long)8);

输出:1

double importedValue = x;
double importedValueConverted = (long) x;

您试图将 double 转换为 long 并将转换的值重新分配给 double。你应该把它分配给long。

于 2012-09-28T18:14:22.257 回答
0

你正在铸造x一个长而不是试图将它分配给一个双倍。

那没有意义。

如果你想要一个长的,你应该使用一个长的。

long longValue = (long) 4.64;

于 2012-09-28T18:14:34.790 回答