IFormatProvider научное преобразование из двойной в строку - количество цифр - PullRequest
4 голосов
/ 07 декабря 2011

У меня проблема с преобразованием из двойного в строковое.

Я хочу конвертировать:

двойное значение: 0.0772486324655191

строковое значение: 0.0772486324655191

и если длина больше 16 цифр после десятичной точки, я хочу это так:

двойное значение: 0,00063500244832493823

строковое значение: 6.3500244832493823e-004

Я попытался преобразовать его с помощью шаблона IFormatProvider:

0.0000000000000000e000

Но результат в первом случае

7.7248632465519100e-002

Как я могу получить количество цифр в моем двойном векторе? Или лучше: как правильно использовать поставщика форматов?

String specifier;
CultureInfo culture;
specifier = "0.0000000000000000e000";
culture = CultureInfo.CreateSpecificCulture("en-US");
Console.WriteLine(DoubleMirrored[0].ToString(specifier, CultureInfo.InvariantCulture));

1 Ответ

4 голосов
/ 08 декабря 2011

Для этого вам обязательно нужно создать собственный форматтер.

Чтобы создать пользовательский форматер, вы должны знать следующее:
string.Format имеет следующую перегрузку: string.Format(IFormatProvider, string, object[]), поэтому вы должны создать IFormatProvider, который будет "предоставлять" ICustomFormatter, который будет обрабатывать ваше пользовательское форматирование.Один и тот же класс может быть легко использован для обоих интерфейсов.

Вот код, который в точности соответствует тому, что вы описываете:

public class DoubleFormatter : IFormatProvider, ICustomFormatter 
{
    // Implementation of IFormatProvider:
    public object GetFormat(Type t) {
        if (t == typeof(ICustomFormatter)) {
            return this;
        }
        return null;
    }
    // Implementation of ICustomFormatter:
    public string Format(string format, object arg, IFormatProvider provider) {
        // Search for the custom "EE" format specifier:
        if (format == null || !format.StartsWith("EE")) return null;
        format = format.Substring(2); // Trim "EE"
        // Determine how many digits before we cutoff:
        int digits;
        if (!int.TryParse(format, out digits)) {
            throw new FormatException("Format must contain digits");
        }

        // Get the value: (note, this will work for any numeric type)
        var value = Convert.ToDouble(arg);
        // Convert to string without using Exponential format:
        var output = value.ToString("0."+(new string('#',digits)), provider);
        // Determine how many digits are showing: (this part isn't culture-compatible)
        var length = output.Length - output.IndexOf(".");
        if (length <= digits) {
            return output;
        } else {
            return value.ToString("E"+format, provider);
        }
    }
}

А вот пример использования этого кода:

var tests = new[]{
    0.0000055555,
    0.00000555555555555555555,
};

var formatter = new DoubleFormatter();
foreach (var t in tests){ 
    var result = string.Format(formatter, "{0:EE15}", t);
    Console.WriteLine(result);
}
...