我正在制作一个应用程序,它需要一堆日记帐分录并计算总和.
当有多个线程调用该addToSum()方法时,下面的方法是线程/并发安全.我想确保每次通话都能正确更新总数.
如果不安全,请说明我必须做些什么来确保螺纹安全.
我需要synchronize获取/放置还是有更好的方法?
private ConcurrentHashMap<String, BigDecimal> sumByAccount;
public void addToSum(String account, BigDecimal amount){
BigDecimal newSum = sumByAccount.get(account).add(amount);
sumByAccount.put(account, newSum);
}
Run Code Online (Sandbox Code Playgroud)
非常感谢!
更新:
谢谢大家的答案,我已经知道上面的代码不是线程安全的.
感谢Vint建议AtomicReference作为替代品synchronize.之前我AtomicInteger用来保存整数和,我想知道BigDecimal是否有类似的东西.
关于两者的赞成和反对,这是一个明确的结论吗?
java concurrency thread-safety bigdecimal concurrent-collections
我正在阅读BigDecimal Class但我无法找到BigDecimal类如何将值存储在计算机内存中的任何信息.
您知道任何可以提供此信息的可靠来源吗?
我有一个BigDecimal计算结果,我需要舍入到最近的指定区间(在这种情况下,它是金融市场的标记大小).
例如价格[Tick Size] - > Rounded Price
100.1 [0.25] -> 100
100.2 [0.25] -> 100.25
100.1 [0.125] -> 100.125
100.2 [0.125] -> 100.25
Run Code Online (Sandbox Code Playgroud)
谢谢.
更新:schnaader的解决方案,翻译成Java/BigDecimal术语:
price = price.divide(tick).setScale(0, RoundingMode.HALF_UP).multiply(tick)
Run Code Online (Sandbox Code Playgroud) 我正在编写处理货币,收费等的代码.我将使用BigDecimal类进行数学和存储,但我们遇到了一些奇怪的东西.
这个说法:
1876.8 == BigDecimal('1876.8')
Run Code Online (Sandbox Code Playgroud)
返回false.
如果我通过格式化字符串运行这些值,"%.13f"我得到:
"%.20f" % 1876.8 => 1876.8000000000000
"%.20f" % BigDecimal('1876.8') => 1876.8000000000002
Run Code Online (Sandbox Code Playgroud)
请注意2最后一个小数位的BigDecimal中的额外值.
我认为BigDecimal应该能够抵消直接在计算机的本机浮点中存储实数的不准确性.这是2从哪里来的?
为什么new BigDecimal("0.015").compareTo(new BigDecimal(0.015))返回-1?如果我希望这两者相等,是否有另一种方法来比较它们?
我正在尝试计算百分比"因子".也就是说,给定20%,将其转换为0.2(我的意图是稍后将值乘以该值并获得20%的值).
无论如何,这个问题与这段代码有关:
public static void main(String[] args) {
int roundingMode = BigDecimal.ROUND_FLOOR;
BigDecimal hundred = new BigDecimal("100");
BigDecimal percentageFactor = null;
BigDecimal percentage = new BigDecimal("20");
BigDecimal value = new BigDecimal("500");
percentageFactor = percentage.divide(hundred, roundingMode);
float f = percentage.floatValue() / hundred.floatValue();
f = value.floatValue() * f;
BigDecimal aux = value.multiply(percentageFactor);
System.out.println("factor:"+percentageFactor.toString());
System.out.println("final falue:"+aux.toString());
System.out.println("Float Value:"+f);
}
Run Code Online (Sandbox Code Playgroud)
我希望这个结果是这样的:
factor: 0.2
final value: 100
float value: 100
Run Code Online (Sandbox Code Playgroud)
但是percentage.divide(hundred, roundingMode);返回零,因此我得到:
factor:0
final falue:0
Float Value:100.0
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?如何正确划分两位大小数?
顺便说一下,我正在使用,BigDecimal因为我将计算货币百分比,所以我想要控制四舍五入.
我注意到这个构造函数有很大的痛苦(即使在Stack Overflow上也是如此).人们使用它,即使文档明确指出:
这个构造函数的结果可能有点不可预测 http://java.sun.com/javase/6/docs/api/java/math/BigDecimal.html#BigDecimal(double)
可能不推荐使用的现有规范:我们建议弃用BigDecimal(double)构造函数,该构造函数目前提供的结果与Double.toString()方法不同.
尽管如此,构造函数还没有被弃用.
我很想听到有关这方面的任何看法.
我知道以下行为是一个老问题,但我仍然不明白.
System.out.println(0.1 + 0.1 + 0.1);
Run Code Online (Sandbox Code Playgroud)
或者即使我使用 BigDecimal
System.out.println(new BigDecimal(0.1).doubleValue()
+ new BigDecimal(0.1).doubleValue()
+ new BigDecimal(0.1).doubleValue());
Run Code Online (Sandbox Code Playgroud)
为什么这个结果是:0.30000000000000004而不是:0.3?
我怎么解决这个问题?
使用以下代码:
BigDecimal x = new BigDecimal("34.5678");
BigDecimal a = x.movePointRight(3);
BigDecimal b = x.scaleByPowerOfTen(3);
BigDecimal c = x.movePointRight(-3);
BigDecimal d = x.scaleByPowerOfTen(-3);
Run Code Online (Sandbox Code Playgroud)
a和b均为34567.8,c和d均为0.0345678.
a.scale()并且b.scale都是1 c.scale()和d.scale()都是7.
这两种方法在什么情况下产生不同的结果?
BigDecimal.add当一个参数具有大指数(9位数)时,方法需要很长时间,而第二个参数具有不同长度的指数.我已经等了5分钟以上,而且还在继续.
这是代码:
@Test
public void testAddBig() throws Exception {
MathContext mc = new MathContext(10, RoundingMode.HALF_UP);
BigDecimal v1 = new BigDecimal("1E+100000000", mc);
BigDecimal v2 = new BigDecimal("1", mc);
System.out.println(v1.add(v2));
}
Run Code Online (Sandbox Code Playgroud)
这是线程转储的一部分:
at java.math.BigInteger.square(BigInteger.java:1884)
at java.math.BigInteger.squareKaratsuba(BigInteger.java:1975)
at java.math.BigInteger.square(BigInteger.java:1888)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2011)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2006)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2012)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2010)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2006)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2012)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.squareToomCook3(BigInteger.java:2011)
at java.math.BigInteger.square(BigInteger.java:1890)
at java.math.BigInteger.pow(BigInteger.java:2263)
at java.math.BigDecimal.bigTenToThe(BigDecimal.java:3543)
at java.math.BigDecimal.bigMultiplyPowerTen(BigDecimal.java:4508)
at java.math.BigDecimal.add(BigDecimal.java:4443)
at java.math.BigDecimal.add(BigDecimal.java:1289)
Run Code Online (Sandbox Code Playgroud)
到底是怎么回事?这是一个错误吗?
bigdecimal ×10
java ×9
api ×1
concurrency ×1
division ×1
fixed-point ×1
intervals ×1
math ×1
rounding ×1
ruby ×1