mikvor / money-conversion Goto Github PK
View Code? Open in Web Editor NEWMoney conversion and arithmetics utility classes.
Money conversion and arithmetics utility classes.
Comparing 2 Money instances is not possible via conversion to double (both long and BigDecimal have higher precision than double). It is not recommended to compare them via BigDecimal due to performance penalty.
We need to implement compareTo on both classes so that we can use it without unneeded conversions.
Should be a simple toString()
call for serializing and MoneyFactory.fromString()
for deserialization. JBoss or some other 3rd party library may be faster in serializing though. More or less an extra feature.
Self-assigned: Will issue pull request a couple of days from now
Hi,
Checking whether an amount is zero, negative, or positive is quite a common usage scenario and adding helper methods would make this check much easier.
Currently we have to create a zero object and compare the actual value with this.
JavaMoney has some great comparators, like .isZero(), isZeroOrNegative(), etc. (https://github.com/JavaMoney/jsr354-ri/blob/master/src/main/java/org/javamoney/moneta/FastMoney.java)
Would be great if Money type had something similar built in.
i.e.
@Override
public boolean isZero() {
return this.number == 0L;
}
@Override
public boolean isPositive() {
return this.number > 0L;
}
@Override
public boolean isPositiveOrZero() {
return this.number >= 0L;
}
@Override
public boolean isNegative() {
return this.number < 0L;
}
@Override
public boolean isNegativeOrZero() {
return this.number <= 0L;
}
BigDecimal implementation is using .signum().
https://github.com/JavaMoney/jsr354-ri/blob/master/src/main/java/org/javamoney/moneta/Money.java
Hi, some users on Android are getting this exception:
W/System.err(24261): java.lang.ArrayIndexOutOfBoundsException: length=16; index=16
W/System.err(24261): at info.javaperformance.money.MoneyLong.add(MoneyLong.java:142)
W/System.err(24261): at info.javaperformance.money.AbstractMoney.add(AbstractMoney.java:34)
W/System.err(24261): at info.javaperformance.money.AbstractMoney.subtract(AbstractMoney.java:55)
Any ideas what might be causing it?
I can not get this on any of the test devices / emulators so just looking for some ideas.
Happens on:
************ DEVICE INFORMATION ***********
Brand: motorola
Device: peregrine
Model: XT1039
Id: LPB23.13-17
Product: peregrine_retde
************ FIRMWARE ************
SDK: 22
Release: 5.1
Incremental: 17
Read your blog post and wanted to try out the Money suggested money implementation.
However after cloning the repo I tried running the tests, and several tests are failing.
junit.framework.AssertionFailedError: Failed to convert 0.05
at info.javaperformance.money.MoneyFactoryTest.testBDConversions(MoneyFactoryTest.java:46)
junit.framework.AssertionFailedError:
Expected :0.25
Actual :0.3
at info.javaperformance.money.MoneyTest.testAdd(MoneyTest.java:35)
junit.framework.AssertionFailedError:
Expected :0.01
Actual :0.02
at info.javaperformance.money.MoneyTest.testAdd2(MoneyTest.java:55)
junit.framework.ComparisonFailure:
Expected :0
Actual :0.045
at info.javaperformance.money.MoneyTest.testSubtract(MoneyTest.java:99)
junit.framework.ComparisonFailure:
Expected :91.1
Actual :91.2
at info.javaperformance.money.MoneyTest.testLongMultiply(MoneyTest.java:113)
junit.framework.ComparisonFailure:
Expected :123.456
Actual :123.5
at info.javaperformance.money.MoneyTest.testTruncateBd(MoneyTest.java:264)
It looks like this is caused by the PR that was merged a couple of weeks ago. If I remove the updates from the PR, the tests pass again.
Here is a test case. Real-world situation is a calculation of a percentage of the total sum.
// allocation is 30%
double allocation = 30;
// total value
Money totalValue = MoneyFactory.fromString("7281.6612");
// money value of 30% allocation
double value = allocation * totalValue.toDouble() / 100;
Money moneyValue = MoneyFactory.fromDouble(value);
// calculate the percentage of the money value
double currentAllocationD = moneyValue.multiply(100)
.divide(totalValue.toDouble(), Constants.DEFAULT_PRECISION)
.toDouble();
Money currentAllocation = moneyValue.multiply(100)
.divide(totalValue.toDouble(), Constants.DEFAULT_PRECISION);
// it should be 30, as set initially.
assertThat(currentAllocationD).isEqualTo(30);
assertThat(currentAllocation.toString()).isEqualTo("30");
The wrong number comes out of the multiplication with 100.
Opening a new ticket since I'm not sure what is the root cause, and the number returned is not negative. Rough testcase:
public void testBigDecimals() {
Money sum = MoneyFactory.fromCharSequence("22543.6089278196672");
Money toAdd = MoneyFactory.fromCharSequence("805.694827586206976");
Money newSum = sum.add(toAdd);
assertTrue("Value too small: " + newSum, newSum.toDouble() > 22000);
}
The sum here should be something above 23000, but this test fails with:
Value too small: 4902.55968169632256
As Money is an immutable class, I was wondering if it wouldn't be good to add autoboxing of some frequently used values (0, 1, 2 ..) and/or some decimals (0.1,0.2 etc)
Or, autobox some integer values and use an LRU cache for the most frequently used decimals.
While testing some calculations I got some unexpected results when adding numbers with many decimals together. It looks like the long normUnitsRes in MoneyLong sometimes overflows on this row in add()
normUnitsRes = m_units + other.m_units * MoneyFactory.MULTIPLIERS[ m_precision - other.m_precision ];
The following testcase demonstrates the behavior
public void testManyDecimals() {
Money sum = MoneyFactory.fromCharSequence("8860.4155830223232");
Money toAdd = MoneyFactory.fromCharSequence("804.798809343434368");
Money newSum = sum.add(toAdd);
assertTrue("Value of newSum is " + newSum, newSum.toDouble() > 0);
}
This returns with
junit.framework.AssertionFailedError: Value of newSum is -8781.529681343794048
Hi,
Quick question, or a feature request: Why is there no multiplication and/or division operations between the Money types?
I'm trying to calculate a simple currency conversion with the rates and am not sure what the best path would be.
Currently the only available path is through long/double conversions. I'm wondering what the reasons are and if it is possible to stay within Money type throughout the operations.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.