Replacement for snprintf

H. S. Teoh hsteoh at
Wed Oct 30 21:52:13 UTC 2019

On Wed, Oct 30, 2019 at 07:11:14PM +0000, berni44 via Digitalmars-d wrote:
> On Wednesday, 30 October 2019 at 17:41:26 UTC, H. S. Teoh wrote:
> > Formatting floating-point numbers is not a trivial task. It's easy
> > to write up something that works for common cases, but it's not so
> > easy to get something to gives the best results in *all* cases.
> I know, that this is something we all wish. Anyway, my goal is set
> somewhat lower: I'd like to replace the existing call to snprintf with
> something that is programmed in D and which should be pure, @safe and
> ctfeable. And ideally it should not be slower then snprintf.

Yeah, I've been waiting for a long time for a pure, @safe, and CTFE-able
floating point formatter in D.  What rumbu said about rounding mode,
though, makes me fear that pure may not be attainable if we're going to
be IEEE-compliant (since accessing the current rounding mode would be
technically impure).

Then again, the CTFE-able version can probably be made pure, since CTFE
cannot change rounding mode in the compiler's runtime environment, so if
we detect CTFE then we can just assume the default rounding mode.

	auto formatFloat(F)(F f) {
		FloatingPointControl fc;
		if (__ctfe)
			return formatFloatImpl(fc.roundToNearest); // pure
			return formatFloatImpl(fc.rounding); // impure

should do it.

> > You probably should use the algorithms referenced above for your
> > implementation,
> I read through the paper for the ryu algorithm and rejected it (at
> least for me; if someone else is goint to implement it and file a PR
> that's fine). My reason for rejecting is, that the algorithm has not
> exactly the same goal as printf, which IMHO means, that it cannot be
> used here; and that it needs a lookuptable, that is too large (300K
> for 128bit reals).

Why is it too large?  Couldn't you generate the table with CTFE? :-D

Or statically generate it and then import it, like std.uni does with the
various Unicode tables (see std.internal.unicode_*).

> Obviously I need to prove, that the algorithm is correct somehow.
> While this can be done for floats by running it on all numbers and
> comparing these results with the result of snprintf (or the result
> calculated by bc), for doubles and reals, this isn't possible anymore
> (a random sample can be tested anyway, but that's no proof).

Are we just copying whatever snprintf does? Is snprintf really a
reliable standard to go by?

> Anyway, I think, that the proof isn't hard to give. The current
> algorithm is short and straight forward. (And: When I implement one of
> the mentioned algorithms, it can still contain bugs, because I made a
> mistake somewhere.)

You don't necessarily have to implement grisu, et al, verbatim, but your
algorithm should at least gracefully handle the special cases and
potentially problematic cases cited in the papers.


Too many people have open minds but closed eyes.

More information about the Digitalmars-d mailing list