问题
I am building a new ecommerce platform using Tomcat/JSTL/MySQL/etc.
I am aware of the various issues related to using floating point calculations - e.g. 12.3456000000000789... I know rounding vs truncation can also be an issue.
Without moving all of the business logic into Java classes, what is the best way to make reliable calculations on currency while still keeping the architecture simple?
My thoughts on possibilities include:
- isolate the problem calculations and deal with them individually
- represent numbers as longs and do calculations using cents
- use BigDecimal and do all calculations in Java
- store numbers in Strings as much as possible
- use <fmt:formatNumber var="... instead of <c:set var="...
I might not be the first to doing this.
What is the most straight forward approach?
回答1:
isolate the problem calculations and deal with them individually
Not an answer. Whatever technique you use will come from elsewhere in your list.
represent numbers as longs and do calculations using cents
Feasible but clumsy, and there are cases in finance where fractions of a cent are valid: for example, foreign exchange.
use BigDecimal and do all calculations in Java
This is the answer. Better still, do the calculations in the database.
store numbers in Strings as much as possible
Not an answer. You still have to calculate, and when you do the technique will come from elsewhere in your list.
use <fmt:formatNumber var="... instead of <c:set var="...
Not an answer. You will certainly have to use formatNumber, but it doesn't address how you are going to calculate. I don't see what c:set has to do with it, it does a different thing. It's not an alternative to numberFormat.
回答2:
Without moving all of the business logic into Java classes, what is the best way to make reliable calculations on currency while still keeping the architecture simple?
Pick simple or reliable - you can't really have both in this case - at least not that simple.
Business logic in a JSP page is a really bad code smell - and it's bad enough in a small, personal project, but why would you do that in an "ecommerce platform"?
Despite your hesitation to do so, I suggest that you move all of your business logic from your JSPs to appropriate java classes.
Better yet, given that you are developing software to deal with financial transactions, do yourself and your potential customers a big favor, and hire a programmer who knows what they are doing.
I realize that this is coming off a bit insulting, but given your obvious lack of familiarity with both the Java programming language and decent coding practices in general, you really have no business writing commercial software that deals with other people's money.
回答3:
Bingo. My problem wasn't in EL at all. Turns out I accidentally had some float fields in the database. When I changed them back to decimals, everything fell into place.
Seems if you pull a decimal out of MySQL, you get a BigDecimal under the covers. So the word is orderly after all.
Thanks all for your input.
see:
<c:set var="tests" value="123.45"/>
<br>tests: ${tests} -- <%= pageContext.findAttribute("tests").getClass() %>
<c:set var="testl" value="${3}"/>
<br>testl: ${testl} -- <%= pageContext.findAttribute("testl").getClass() %>
<c:set var="testd" value="${123.45}"/>
<br>testd: ${testd} -- <%= pageContext.findAttribute("testd").getClass() %>
<c:set var="testbd" value="<%= new BigDecimal(\"123.45\") %>"/>
<br>testbd: ${testbd} -- <%= pageContext.findAttribute("testbd").getClass() %>
<c:set var="testbd" value="${testbd+1}"/>
<br>testbd: ${testbd} -- <%= pageContext.findAttribute("testbd").getClass() %>
<sql:query var="items">
SELECT * FROM items WHERE itemid=?;
<sql:param value="55" />
</sql:query>
<c:set var="testdb" value="${items.rows[0].price}"/>
<br>testdb: ${testdb} -- <%= pageContext.findAttribute("testdb").getClass() %>
<%-- output
tests: 123.45 -- class java.lang.String
testl: 3 -- class java.lang.Long
testd: 123.45 -- class java.lang.Double
testbd: 123.45 -- class java.math.BigDecimal
testbd: 124.45 -- class java.math.BigDecimal
testdb: 129.95 -- class java.math.BigDecimal
--%>
来源:https://stackoverflow.com/questions/14345147/best-practice-for-financial-calculations-using-jstl-tomcat