Formatting -0.0 as 0.0

Bastiaan Veelo Bastiaan at Veelo.net
Mon Oct 18 11:58:36 UTC 2021


On Friday, 15 October 2021 at 14:09:32 UTC, Steven Schveighoffer 
wrote:
> The only way I can think of that isn't really intrusive (like 
> your `posZero` thing) is to define your own `writef`/`format` 
> wrappers (what I'd do is check any doubles, and replace them 
> when necessary).

I have settled on a wrapper. @kinke has helped me to deal with 
fast-math, so this can be branchless.

```d
import std.traits : isSomeChar, isSomeString;

/** Wraps std.format.format converting any negative zero floating 
point to positive. */
immutable(Char)[] fmt(Char, Args...)(in Char[] spec, Args args)
if (isSomeChar!Char)
{
     import std.format : format;

     return format(spec, PosZero!args);
}

/** idem */
typeof(spec) fmt(alias spec, Args...)(Args args)
if (isSomeString!(typeof(spec)))
{
     import std.format : format;

     return format!spec(PosZero!args);
}

// Maps args, adding 0.0 if floating point.
private template PosZero(args...)
{
     import std.meta : staticMap;

     template posZero(alias arg)
     {
         import std.traits : isFloatingPoint;

         static if (isFloatingPoint!(typeof(arg)))
         {
             version (LDC)
             {
                 import ldc.attributes : llvmFastMathFlag;
                 @llvmFastMathFlag("clear") auto posZero() {return 
arg + 0.0;}
             }
             else
                 auto posZero() {return arg + 0.0;}
         }
         else
             alias posZero = arg;
     }

     alias PosZero = staticMap!(posZero, args);
}

unittest
{
     import std.format : format;

     //assert((-0.0).format!"%3.1f" == "-0.0");
     assert((-0.0).fmt!"%3.1f" == "0.0");
     //assert(format("%3.1f", -0.0) == "-0.0");
     assert(fmt("%3.1f", -0.0) == "0.0");

     string foo(immutable double d)
     {
         return d.fmt!"%3.1f";
     }
     assert(foo(-0.0) == "0.0");

     //assert(format!"%d;%3.1f;%3.1f;%3.1f;%s"(42, -0.0, 3.14, 
-0.0, "!") == "42;-0.0;3.1;-0.0;!");
     assert(fmt!"%d;%3.1f;%3.1f;%3.1f;%s"(42, -0.0, 3.14, -0.0f, 
"!") == "42;0.0;3.1;0.0;!");
     //assert(format("%d;%3.1f;%3.1f;%3.1f;%s", 42, -0.0, 3.14, 
-0.0, "!") == "42;-0.0;3.1;-0.0;!");
     assert(fmt("%d;%3.1f;%3.1f;%3.1f;%s", 42, -0.0, 3.14, -0.0f, 
"!") == "42;0.0;3.1;0.0;!");
     assert(fmt!""() == format!""());
     assert(fmt("") == format(""));
}
```

Love this language!

-- Bastiaan.


More information about the Digitalmars-d mailing list