解决 0d 和 -.1d 的字符串表示形式的双精度问题,以便更清洁 UI
Solving the double precision issue for string representations of 0d and -.1d for cleaner UI
不是 Is floating point math broken? 的副本如果您花时间阅读问题,我正在寻找用字符串表示这些浮点数的更好方法。
我有一个数字 up/down 控件,本质上是一个普通的文本框,旁边有上下按钮,将其值存储为双精度值。我一直运行遇到上下循环的问题,当值为(或应该为)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;
}
}
对于任何其他寻找正确答案的人,而不仅仅是那些试图强迫您使用小数的人,我发现这对于 UI 精确双精度值的表示很有效。我通过四舍五入到 10 位牺牲了一些分辨率,但在我的应用程序中 10 位就可以了。至于转换为十进制然后返回双精度,这避免了使用双精度可能导致的复合错误。
[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;
}
}
不是 Is floating point math broken? 的副本如果您花时间阅读问题,我正在寻找用字符串表示这些浮点数的更好方法。
我有一个数字 up/down 控件,本质上是一个普通的文本框,旁边有上下按钮,将其值存储为双精度值。我一直运行遇到上下循环的问题,当值为(或应该为)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;
}
}
对于任何其他寻找正确答案的人,而不仅仅是那些试图强迫您使用小数的人,我发现这对于 UI 精确双精度值的表示很有效。我通过四舍五入到 10 位牺牲了一些分辨率,但在我的应用程序中 10 位就可以了。至于转换为十进制然后返回双精度,这避免了使用双精度可能导致的复合错误。
[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;
}
}