Hi Matt,
It sounds like a good addition to [text]. What do you think about creating a
JIRA issue and preparing a pull request? It would be easier to review the
implementation that way IMO.
There are some users that reply to github pull requests too, but normally don't
read the mailing list threads.
So we can both review the code (see whether it really makes sense to have it in
[text], which package to use, etc) and wait to see if any external user chimes
in.
The comments in the pull request would be mirrored to the JIRA issue too, so
anyone not using GH could participate in the code review & discussion too.
Cheers
Bruno
On Saturday, 12 June 2021, 3:52:54 pm NZST, Matt Juntunen
<[email protected]> wrote:
Hello,
I mentioned a while ago the idea of moving a utility that I find quite useful
from commons-geometry to commons-text, which would be a more appropriate home
for it. There was not any interest at the time but I've made a few improvements
to the class and I'd like to try again. The utility in question is the
DoubleFormats [1] class. This class contains factory methods for producing
lightweight, thread-safe DoubleFunction<String> instances for converting
doubles to decimal strings in different formats. The class is specifically
designed for data output; no localization is performed. It is used in
commons-geometry to provide a way to control the precision and formatting of
double values in text-based geometric data formats such as OBJ. I've found that
although the JDK provides a number of different ways to format doubles (eg,
String.format, DecimalFormat, BigDecimal, etc), none of them have fit the
requirements for performant, thread-safe data output. Hence, the reason for
this class.
Below are examples of each of the types of formats available and some outputs.
The arguments passed to each method are the precision (maximum number of
non-zero decimal digits) and min exponent (base 10 exponent for the smallest
non-zero number that should be represented).
// plain decimal representation; no scientific format
DoubleFunction<String> plain = DoubleFormats.createPlain(5, -3);
plain.apply(1); // 1.0
plain.apply(1e10); // 10000000000.0
plain.apply(1234.567); // 1234.6
plain.apply(0.00356); // 0.004
// scientific format
DoubleFunction<String> sci = DoubleFormats.createScientific(5, -3);
sci.apply(1); // 1.0
sci.apply(1e10); // 1.0E10
sci.apply(1234.567); // 1.2346E3
sci.apply(0.00356); // 4.0E-3
// engineering format
DoubleFunction<String> eng = DoubleFormats.createEngineering(5, -3);
eng.apply(1); // 1.0
eng.apply(1e10); // 10.0E9
eng.apply(1234.567); // 1.2346E3
eng.apply(0.00356); // 4.0E-3
// default format; uses the Double.toString() convention of representing
// numbers less that 10^-3 or greater than 10^7 using scientific format and
// other numbers using plain decimal format
DoubleFunction<String> def = DoubleFormats.createDefault(5, -3);
def.apply(1); // 1.0
def.apply(1e10); // 1.0E10
def.apply(1234.567); // 1234.6
def.apply(0.00356); // 0.004
The performance of all of these methods is comparable to DecimalFormat or
BigDecimal. The benchmark output below shows the results of formatting 10000
double values using standard Double.toString(), a simple BigDecimal conversion,
DecimalFormat (single instance), and a function returned from
DoubleFormats.createDefault(). Double.toString() is the clear winner but the
rest are all quite close.
Benchmark (size) Mode Cnt
Score Error Units
DoubleFormatsPerformance.doubleToString 10000 avgt 5
3837610.399 ± 62668.705 ns/op
DoubleFormatsPerformance.bigDecimal 10000 avgt 5
6279807.365 ± 93566.619 ns/op
DoubleFormatsPerformance.decimalFormat 10000 avgt 5
5787717.633 ± 168626.950 ns/op
DoubleFormatsPerformance.doubleFormatsDefault 10000 avgt 5
5779534.166 ± 69496.434 ns/op
Please let me know if there is any interest in moving this class to
commons-text. It's primary advantages are that it is
-thread-safe (unlike DecimalFormat),
-performant (unlike String.format()), and
-allows a variety of output formats (unlike BigDecimal).
I would also be open to discussion and improvements on the
design/implementation.
Regards,
Matt J
[1]
https://github.com/apache/commons-geometry/blob/master/commons-geometry-io-core/src/main/java/org/apache/commons/geometry/io/core/utils/DoubleFormats.java