You're mixing oldschool scriptlets with EL and expecting that they share the same variable scope. This is not true. EL (those ${}
things) searches in respectively the page, request, session and application scopes for the first non-null
attribute matching the given name and returns it. It does not access the scriptlet local scope in any way.
Basically, to make
<%double distance=geo.getDistance(geo.getLatitude(), geo.getLongitude(), lat, lng);%>
available as ${distance}
, you need to set it in any of the desired EL scopes, e.g. the request scope
<%
double distance=geo.getDistance(geo.getLatitude(), geo.getLongitude(), lat, lng);
request.setAttribute("distance", distance);
%>
Once done that, then you can just use
<fmt:formatNumber pattern="0.0" value="${distance}"/>
without the need to massage with <c:set>
, by the way.
Note, a said, mixing scriptlets with EL is not the normal practice. You use the one or the other. In this particular case, that Java code belongs in a preprocessing servlet class.
Also note that your concrete problem is not specifically related to JSTL. You just pointed it a non-existent variable.