Calculating and displaying floating point numbers in JSP
-
03-07-2019 - |
Question
I'm trying to take two 7 digit numbers (source and target record counts) and calculate the percentage of missing records in the target count.
For example, my record counts could be 4084094 for the source, and 4081313 for the target. I'm also using the follow formula to calc the percentage: ((1 - (target / source)) * 100)
For my example, I should get the value of about .0681%
I'm am new to Java and JSP, and I'm not able to get the percentage to display correctly. I seem to only get a value rounded down to 0.
I've also tried BigDecimal, to no avail.
Even the following simple code displays the value of 1-1, so I obviously am doing somthing seriously wrong:
<%
BigDecimal percentMiss;
long tmp = 600/500;
percentMiss = BigDecimal.valueOf(tmp);
%>
<%=percentMiss.toString()%>-<%=tmp%>
Solution
The problem is in the following line
long tmp = 600/500;
You cannot store floating point numbers in a long, instead you should consider using the following code:
double tmp = (double)600 / (double)500;
and then display tmp, which should have a value somewhere between 0 and 1 (in your case 1.2, because you have to change your calculation to 500 / 600)
OTHER TIPS
The problem is obviously that you are dividing two long numbers.
I would recommend using DecimalFormat to display the number. If you are using JSTL, then an even better solution is to use the format tags:
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<fmt:formatNumber value="${value}" minFractionDigits="2" maxFractionDigits="2"/>
Your problem is that 600 and 500 are integer values, and a division between them will have an integer result, which you assign to a long integer. After this, the fractional part of the result is gone (twice) and you can't get it back.
In order to get a fractional result, at least one of the input values of the division needs to be non-integer. You can achieve this by casting them to double
or float
, or by making the literals explicitly double or float like this:
500.0 // implicitly double
500f // float literal
500d // double literal
However, printing the result of a double/float divison will often have more decimal places than you want even if they shouldn't be in the result (e.g. 1/10
can result in 0.100000001490116119384765625
), due to the way these numbers are stored as binary fractions.
You can eliminate these unwanted digits by using java.lang.DecimalFormat
, but BigDecimal
is a better option, since it internally uses decimal fractions and will therefore deliver the actually correct results while offering exact control over rounding modes. Of course, this requires you to use BigDecimal
for the calculation itself, rather than as "voodoo ingredient" to fix an already broken result.
new BigDecimal(600).divide(new BigDecimal(500))
Read the API documentation for BigDecimal
for more information.