See the question and my original answer on StackOverflow

Binary floating point math is like this.

But in this case, you can implement a custom number formatter, for example like this:

public class DoubleFormatter : INumberFormatter2, INumberParser
{
    public virtual string Format { get; set; } = "{0:F2}"; // by default we use this but you can change it in the XAML declaration
    public virtual string FormatDouble(double value) => string.Format(Format, value);
    public virtual double? ParseDouble(string text) => double.TryParse(text, out var dbl) ? dbl : null;

    // we only support doubles
    public string FormatInt(long value) => throw new NotSupportedException();
    public string FormatUInt(ulong value) => throw new NotSupportedException();
    public long? ParseInt(string text) => throw new NotSupportedException();
    public ulong? ParseUInt(string text) => throw new NotSupportedException();
}

Note: it's not documented AFAIK but an INumberFormatter2 must also implement INumberParser otherwise you get "invalid argument" of more exotic cryptic errors...

Sample XAML:

<StackPanel>
    <StackPanel.Resources>
        <local:DoubleFormatter x:Key="df" /> <!-- change Format here -->
    </StackPanel.Resources>
    <NumberBox NumberFormatter="{StaticResource df}" Value="{x:Bind MyFloatValue, Mode=TwoWay}" />
</StackPanel>