为更清晰的UI解决0d和-.1d的字符串表示的双精度问题

时间:2016-03-31 14:58:42

标签: c# double

不是Is floating point math broken?的副本如果您花时间阅读问题,我正在寻找更好的方法来表示字符串中的这些浮点数。

我有一个数字上/下控制,基本上是一个普通的文本框,旁边有向上按钮,可以将其值存储为double。我在上下循环时遇到问题,当值为(或应该是)0或-1时,文本框显示" 1.38777878078145E-16"和" -0.0999999999999999"分别(以及其他)这使控制感觉混乱。

我得到double的浮点精度意味着值被截断并且小数的绝对精度比双精度更长。准确地表示-.1d的实际值对我来说并不像它的清晰表示那么重要,这意味着我希望-.1d(-0.0999999999999999)简单地显示为" - 。1"

不要假设我的例子中所有值都在一个小数内,尽管精度不是非常重要的粒度。

现在我只是在我的双字符串转换器中捕获字符串并处理它,但是有更好的方法吗?

不,由于它的开销,我不能使用十进制。

[ValueConversion(typeof(Double), typeof(String))]
public class DoubleToStringValueConverter : IValueConverter
{
    public object Convert(object value,
                          Type targetType,
                          object parameter,
                          System.Globalization.CultureInfo culture)
    {
        string res = ((double)value).ToString(culture);
        if (res == "1.38777878078145E-16") res = "0";
        if (res == "-0.0999999999999999") res = "-0.1";
        return res;
    }

    public object ConvertBack(object value,
                              Type targetType,
                              object parameter,
                              System.Globalization.CultureInfo culture)
    {
        string val = value as string;
        double res = 0d;
        double.TryParse(val, System.Globalization.NumberStyles.Float, culture, out res);
        return res;
    }

}

1 个答案:

答案 0 :(得分:0)

对于寻找正确答案的其他人而不仅仅是那些试图强迫您使用小数的人,我发现这对于精确双值的UI表示非常有用。我通过四舍五入到10个位置来牺牲一些分辨率,但在我的应用中,10个位置就好了。至于转换为十进制然后再转换为double,这可以避免使用double的复合错误。

[ValueConversion(typeof(Double), typeof(String))]
public class DoubleToStringValueConverter : IValueConverter
{
    public object Convert(object value,
                          Type targetType,
                          object parameter,
                          System.Globalization.CultureInfo culture)
    {
        decimal display = Math.Round(System.Convert.ToDecimal((double)value), 10) / 1.000000000000000000000000000000000m;
        value = System.Convert.ToDouble(display);
        string res = display.ToString(culture);

        return res;
    }

    public object ConvertBack(object value,
                              Type targetType,
                              object parameter,
                              System.Globalization.CultureInfo culture)
    {
        string val = value as string;
        double res = 0d;
        double.TryParse(val, System.Globalization.NumberStyles.Float, culture, out res);

        return res;
    }
}