我需要编写一个小型Java程序来处理涉及金钱的计算。因此它需要具有准确性。 (例如:没有float
/ double
个变量,只有long
)。
不幸的是,我需要使用的原始值是通过一个只能将变量读取为“double”的方法导入的。
现在,我尝试使用类似于:
的方法将其转换为long
double importedValue = x;
double importedValueConverted = (long) x;
然而,当我尝试将importedValueConverted除以另一个“long”变量时,我得到:
要求:长 发现:双倍 错误:可能损失精度
为什么?
答案 0 :(得分:3)
double importedValue = x;
double importedValueConverted = (long) x;
请注意,这两个变量都声明为“double”。这会导致您的错误(释义):(您正在进行的操作需要a long
(但在尝试时发现了)double
。
你想:
double importedValue = x;
long importedValueConverted = (long) x;
答案 1 :(得分:2)
忘记所有的铸造业务。如果您正在使用财务计算,您可以直接使用BigDecimal来包装您所谓的方法返回的双精度数,并使用BigDecimal提供的适合您需要的舍入机制。
答案 2 :(得分:1)
<强>更新强>
这篇文章提出了一个我认为没有回答过的问题 - 为什么要使用int
,或者更好,long
或BigDecimal
进行货币计算。这在这里得到解答:
Why not to use double or float to represent currency (or where any exact calculations are needed)?
因为浮点数和双打数不能准确地代表大多数基数10 实数。
即使使用BigDecimal
,也必须使用String
构造函数而不是float
构造函数。
这一切都说,你最好的选择是:
long
(将每个美元金额乘以100)这将保持所需的准确性。显然这个解决方案考虑到了美元,任何对外币的转换都需要适当的考虑。
考虑舍入到最接近的long
值而不是强制转换:
double d = 1234.56;
long x = Math.round(d);
我真的问你为什么要从double
转到long
,因为这会让你失去小数值的精确度。
如果你想保持一定的精确度(比方说多达3位数),你绝对只能用长这样做,你可以将两个双倍乘以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
答案 3 :(得分: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。你应该把它分配给很长时间。
答案 4 :(得分:0)
您要将x
投射到比尝试将其分配给双精灵更长的时间。
这没有用。
如果你想长,你应该使用很长的。
long longValue = (long) 4.64;
答案 5 :(得分:0)
为什么不看BigDecimal。我使用它时效果很好。小心使用Double ctor虽然Double不是那么精确(例如它不能精确地存储0.1)。将String ctor用于BigDecimal
可能更有用