我需要在Java中用完美的精度和小数点后固定的小数点数表示一些数字;小数点后,我不在乎。 (更具体地说 - 金钱和百分比。)
我现在使用Java自己的BigDecimal,但我发现, 真的 很慢,它开始显示在我的应用程序中。
所以我想用“常规”整数和定点算术来解决它(长整数对于我的目的而言具有足够的精度)。
现在,我认为我不是第一个遇到这种问题的人,并且已经有了一个库,已经实现了乘法/除法 - 但似乎它不是。
现在,我很可能自己写(我可能会),但是,我真的是第一个需要这个的人吗?是不是已经有了一些库?
答案 0 :(得分:4)
你完全确定BigDecimal是性能问题吗?您是否使用了分析器来查找?如果是,可以帮助的两个选项是:
1)使用long
并将所有值乘以一个因子(例如,如果您对分数感兴趣,则为100)。
2)使用专门设计的类来实现与BigDecimal
类似的内容,但在内部使用long
。我不知道是否存在一个好的开源库(可能是Java Math Fixed Point Library?)。很久以前我(2001年我相信)为J2ME写了一篇这样的课程。要做对,这有点棘手。请注意BigDecimal
内部也使用long
,除非需要高精度,所以此解决方案在大多数情况下只会有所帮助。
由于舍入和精度问题,在许多情况下使用double
不是一个好选择。
答案 1 :(得分:3)
decimal4j是一个基于long的快速固定精度算术的Java库,支持最多18个小数位。
免责声明:我参与了decimal4j项目。
答案 2 :(得分:0)
尽管这并不是您要问的,但这可以加快您的应用程序的速度,而无需离开BigDecimal
:
自Java 8起,此问题由BigDecimal
本身解决。添加了new class MathContext
,并限制了运算的精确度。
var num = new BigDecimal("1234.56780", new MathContext(10, RoundingMode.DOWN));
要注意的是,精度10
不适用于小数点后的数字。它适用于有效位数。对于1234.50
,需要6。
对于1_500_000_000.100
,需要13以保持数字不变。
因此,当您的精度为10并计算数十亿捷克克朗时,精度可能会受到影响。
仍然,例如1000的精度比无限精度(我认为是默认值)要快得多。
这也可以应用于单个操作:
BigDecimal n = new BigDecimal("0.12345");
n = n.pow(2, new MathContext(1000, RoundingMode.DOWN));
n = n.pow(2, new MathContext(1000, RoundingMode.DOWN));
n = n.pow(2, new MathContext(1000, RoundingMode.DOWN));
n = n.pow(2, new MathContext(1000, RoundingMode.DOWN));
答案 3 :(得分:-1)
不确定为什么需要一个库。
例如,假设您要添加两个具有相同固定精度的长片
long c = a + b;
假设您有一个固定的精度数,您希望用整数
复数long c = a * i;
假设您要将数字除以整数舍入为零
long c = a / i;
假设您要打印一个带有3位小数的固定精度数字。
System.out.println(c / 1e3);
也许你正在考虑这个问题,并假设你需要一个库来存放一切。
如果您使用的是long
或double
,您可能需要使用少量辅助方法进行舍入,但您不需要这样的库。