java java中具有快速性能的定点算法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11916308/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
fixed point arithmetics in java with fast performance
提问by Karel Bílek
I need to represent some numbers in Java with perfect precision and fixed number of decimal points after decimal point; after that decimal point, I don't care. (More concretely - money and percentages.)
我需要在Java中以完美的精度和固定的小数点后小数点数来表示一些数字;在那个小数点之后,我不在乎。(更具体地说 - 金钱和百分比。)
I used Java's own BigDecimal now, but I found out, that it's reallyslow and it starts to show in my application.
我现在使用 Java 自己的 BigDecimal,但我发现它真的很慢,并且开始显示在我的应用程序中。
So I want to solve it with a "regular" integers and a fixed-point arithmetics (long integers have big enough precision for my purposes).
所以我想用“常规”整数和定点算术来解决它(长整数对于我的目的来说具有足够大的精度)。
Now, I would think that I am not the first one who has this kind of problem and there would be already a library for that, that already has multiplication/division implemented - but it seems that it isn't.
现在,我认为我不是第一个遇到这种问题的人,并且已经有一个库,它已经实现了乘法/除法 - 但似乎不是。
Now, I very probably can write it myself (and I probably will), but really, am I really the first person that needs this? Isn't there already some library for that?
现在,我很可能可以自己编写它(我可能会),但真的,我真的是第一个需要它的人吗?不是已经有一些图书馆了吗?
采纳答案by Thomas Mueller
Are you completelysure BigDecimal is the performance problem? Did you use a profiler to find out? If yes, two options that could help are:
您是否完全确定 BigDecimal 是性能问题?你用分析器找出来了吗?如果是,有两个可能有帮助的选项是:
1) Use long
and multiply all values by a factor (for example 100 if you are interested in cents).
1) 使用long
所有值并将其乘以一个因子(例如,如果您对美分感兴趣,则为 100)。
2) Use a specially designed class that implements something similar to BigDecimal
, but using long
internally. I don't know if a good open source library exists (maybe the Java Math Fixed Point Library?). I wrote one such class myself quite a long time ago (2001 I believe) for J2ME. It's a bit tricky to get right. Please note BigDecimal
uses a long
internally as well except if high precision is needed, so this solution will only help a tiny bit in most cases.
2) 使用一个专门设计的类,它实现了类似于 的东西BigDecimal
,但在long
内部使用。我不知道是否存在一个好的开源库(也许是Java Math Fixed Point Library?)。我很久以前(我相信是 2001 年)为 J2ME 自己写了一个这样的类。做对有点棘手。请注意,除非需要高精度,否则内部也BigDecimal
使用 a long
,因此该解决方案在大多数情况下只会有一点帮助。
Using double
isn't a good option in many cases, because of rounding and precision problems.
double
由于舍入和精度问题,在许多情况下使用并不是一个好的选择。
回答by marco
回答by Ondra ?i?ka
Although this is not exactly what you are asking about, this can speed up your app without leaving BigDecimal
:
虽然这不是您所要问的,但这可以在不离开的情况下加速您的应用程序BigDecimal
:
Since Java 8, this is solved by BigDecimal
itself. A new class MathContext
was added and limits the precision to which the operations are calculated.
从 Java 8 开始,这可以BigDecimal
自行解决。添加了一个新类MathContext
并限制了计算操作的精度。
var num = new BigDecimal("1234.56780", new MathContext(10, RoundingMode.DOWN));
The catch is that the precision 10
does not apply to digits after decimal point. It applies to the number of significant digits. For 1234.50
, 6 is needed.
For 1_500_000_000.100
, 13 is needed to keep the number as is.
So the precision might suffer when you had a precision of 10 and counted billions of Czech Korunas.
Still, a precision of, say, 1000, is way faster than unlimited precision (which is I think the default).
问题是精度10
不适用于小数点后的数字。它适用于有效位数。对于1234.50
,需要 6。
对于1_500_000_000.100
,需要 13 来保持数字不变。
因此,当您拥有 10 的精度并计算数十亿捷克克朗时,精度可能会受到影响。
尽管如此,例如 1000 的精度比无限精度(我认为这是默认值)要快得多。
This can also be applied to the individual operations:
这也可以应用于单个操作:
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));
回答by Peter Lawrey
Not sure why you need a library for it.
不知道为什么你需要一个图书馆。
For example, say you want to add two longs with the same fixed precision
例如,假设您要添加两个具有相同固定精度的 long
long c = a + b;
Say you have a fixed precision number you want to multiple by an integer
假设你有一个固定的精度数,你想乘以一个整数
long c = a * i;
Say you want to divide a number by a integer rounding to zero
假设你想用一个整数除以一个四舍五入为零的数字
long c = a / i;
Say you want to print a fixed precision number with 3 decimal places.
假设您要打印一个带有 3 个小数位的固定精度数字。
System.out.println(c / 1e3);
Perhaps you are over thinking the problem and assuming you need a library for everything.
也许您过度思考这个问题并假设您需要一个库来处理所有事情。
If you are using long
or double
you might want a small number helper methods for rounding, but you don't need a library as such.
如果您正在使用long
或者double
您可能需要少量辅助方法进行舍入,但您不需要这样的库。