I've now submitted a revised float.__format__, and one for complex
too. It is correct (nearly) but I have two observations:
1. The contract for Double.toString(double) appears to be exactly
what we need for float.__repr__, but it doesn't keep its contract
However, I am using this for repr().
2. The conversions in float.__format__ (and my fixed version of
round) are based on BigDecimal. This is correct, but slow for
numbers with large exponent, especially when the exponent is large
To do any better than this, I believe we would have implement our
own conversion, as CPython have. This may yet have to happen if
performance of float.__format__ turns out to be an issue.
%-formatting of floats is uncorrected. I'd like to make it use the
new code but this isn't entirely straightforward.
On 18/04/2014 15:18, Jeff Allen wrote:
This was harder than it looked. I've pretty much written it three
times over now. This post is by way of a progress report.
I'm getting good (perfect maybe) conformance with CPython for both
new-style format calls and float.__repr__. I've done this by
evolving the InternalFormatter class (in
core/stringlib/Formatter.java), beyond all recognition.
I'm getting BigDecimal to do conversion and rounding for format
types accepted by float.__format__, and for __str__. This is fully
BigDecimal rounding cannot be made to emulate float.__repr__ by
itself, but it appears that Double.toString(double) does exactly
what we need when it gives answers up to 17 digits. Occasionally
it provides 18 and we have to do some rounding. Rounding a rounded
result isn't quite right (think 0.49 rounded to 1 d.p. then to an
integer), but it seems to work here.
I have evolved the format parsing, and put the padding code in the
formatter, to simplify the division of responsibilities between
the client (float) and the formatter. Now it looks a lot like
using a StringBuilder. I think this will increase cohesion, and
reduce the number of source files, once applied to all the types
where we currently use InternalFormatSpec.
Our way of supplying defaults, for the conversion type and
alignment, diverges from CPython in a way that seems ultimately to
complicate the client code. I have moved it closer to the CPython
approach, which supplies
defaults when the specification is parsed. In passing, I've
addressed this issue: http://bugs.python.org/issue12546
which exists unreported in Jython.
complex is in a worse state than float, now I look: we are
skipping a ton of tests. I'll apply my work there too.
I'm leaving %-formats alone for now, although they also fail
tests. I'd like to re-use what I've done for that. With that in
view, I've chosen to support alternate (#g) format in my code,
temporarily defining h-format to mean that. I get agreement
between the bogus format(x, "h") and "%#g" % x in CPython.
On 09/04/2014 08:02, Jeff Allen wrote:
I wrote a pretty good replacement for core.stringlib.Formatter, based on
java.text.DecimalFormatter. It agrees with CPython for all "reasonable"
precisions, that is to say up to 16 significant figures, and no-one has
had to take the log of anything. It can provide float.__str__ and
float.__repr__ more cleanly than at present too.
But it fails tests like this: AssertionError:
I haven't come across any cases where the problem is that the actual
float value is different (considered at the bit-level using
float.hex()); it's all on the output formatting. CPython appears to give
us the exact value -- there is always a finite answer, though it may
have a thousand digits. DecimalFormatter, which is at bottom just
Double.toString(), gives us just enough digits to differ from the next
float bit pattern.
Experiments with BigDecimal suggest I can get exact conformance by that
route and it seems worth the attempt, so I'm going that way.
Learn Graph Databases - Download FREE O'Reilly Book
"Graph Databases" is the definitive new guide to graph databases and their
applications. Written by three acclaimed leaders in the field,
this first edition is now available. Download your free book today!
Jython-dev mailing list