如果你绝对不能使用BigDecimal并且不想使用双精度数,那么使用long来做
fixed-point arithmetic(所以每个long值代表分数,例如).这将使你代表18位有效数字.
我会说使用joda-money,但这会使用BigDecimal.
编辑(因为上面没有真正回答问题):
免责声明:如果准确性对你很重要,请在don’t use double to represent money.但是看起来海报并不需要准确的准确性(这似乎是关于金融定价模型,可能有超过10 ** – 12内置的不确定性) ,更关心性能.假设是这种情况,使用double是可以原谅的.
通常,double不能精确地表示小数.那么,双重是多么不精确?对此没有简短的答案.
double可能能够很好地表示一个数字,你可以将数字读入一个double,然后再将其写回,保留15个十进制数字的精度.但由于它是二进制而不是小数,它不可能是精确的 – 它是我们希望表示的值,加上或减去一些错误.当执行涉及不精确双精度的许多算术运算时,该误差的量可能随着时间的推移而累积,使得最终乘积具有少于十五个十进制数字的精度.少了几个?那要看.
考虑以下函数,该函数采用1000的第n个根,然后将其自身乘以n次:
private static double errorDemo(int n) {
double r = Math.pow(1000.0, 1.0/n);
double result = 1.0;
for (int i = 0; i < n; i++) {
result *= r;
}
return 1000.0 - result;
}
结果如下:
errorDemo( 10) = -7.958078640513122E-13
errorDemo( 31) = 9.094947017729282E-13
errorDemo( 100) = 3.410605131648481E-13
errorDemo( 310) = -1.4210854715202004E-11
errorDemo( 1000) = -1.6370904631912708E-11
errorDemo( 3100) = 1.1107204045401886E-10
errorDemo( 10000) = -1.2255441106390208E-10
errorDemo( 31000) = 1.3799308362649754E-9
errorDemo( 100000) = 4.00075350626139E-9
errorDemo( 310000) = -3.100740286754444E-8
errorDemo(1000000) = -9.706695891509298E-9
请注意,累积不准确度的大小并不会与中间步骤的数量成正比地增加(实际上,它不是单调增加的).给定一系列已知的中间操作,我们可以确定不准确度的概率分布;虽然这将具有更宽的范围,但是更多的操作,确切的数量将取决于输入计算的数字.不确定性本身是不确定的!
根据您正在执行的计算类型,您可以通过在中间步骤之后舍入到整个单位/整分来控制此错误. (考虑一个银行账户持有100美元,每月6%的利息复合,每月0.5%的利息.在第三个月的利息被记入后,你想要余额是101.50美元还是101.51美元?)拥有双重支架对于分数单位(即分数)的数量而不是整数单位的数量会使这更容易 – 但如果你这样做,你也可以只使用我上面建议的多数.
免责声明:浮点错误的积累使得使用双倍数额的资金可能非常混乱.作为一个Java开发人员,他曾多次使用double来表示多年来对他的任何打击,我会使用十进制而不是浮点运算来计算任何涉及金钱的重要计算.