Можно ли форматировать поплавок в ненаучном формате? - PullRequest
3 голосов
/ 03 июля 2010

Я пытаюсь преобразовать число с плавающей точкой в ​​строку, не получая научное (1.13E-8) форматирование.

Я ищу некоторую комбинацию спецификаторов "F" и "R".Я хочу, чтобы F не использовал научный стиль, но я также хочу, чтобы R использовал как можно меньше места для точного представления числа.

Итак, с учетом 0,000000001, строковая версия должна быть0,000000001.Не 1E-09 и не 0,000000001000.

Можно ли сказать системе "сделать ее фиксированной точкой, но использовать минимальные цифры, необходимые для точного указания числа"?

Если нет,каким будет хороший обходной путь?Я думал: использовать точность 20, а затем просто взломать конечные 0, если есть '.'в строке.Что-нибудь лучше?

Редактировать:

Вот версия, которую я использовал.Я действительно надеялся, что будет спецификатор формата, который я мог бы использовать, чтобы сделать это вместо этого.

var s = f.ToString("F20");
if (s.Contains("."))
{
    s = s.TrimEnd('0').TrimEnd('.');
}

Ответы [ 2 ]

1 голос
/ 24 декабря 2011

Следующее будет отображать только значащие цифры после десятичной точки, до 10 дней.

var format = "#0.##########";

string.Format(1.23, format);
// 1.23

string.Format(1.23456, format);
// 1.23456

string.Format(1.230045, format);
// 1.230045

string.Format(1.2345678912345, format);
// 1.2345678912

Ключом здесь является то, что символ # выводит цифру, только если это значительный .

Надеюсь, это пойдет как минимум к тому, что вы хотите, по крайней мере.Если нет, вы всегда можете написать кастом IFormatProvider.

1 голос
/ 24 декабря 2011

Обратите внимание, что «точно указать номер» может быть невозможным. Число может включать повторение в базе 2. Подумайте о том, как 1/3 повторяется в базе 10 как 0.33333333.... Это также происходит в базе 2, только хуже. Тем не менее, вы можете использовать «r», чтобы получить значение, которое будет туда и обратно.

Использование "F20", а затем обрезка не приведет к с тем же результатом, что и смещение десятичного разряда в формате "r". На Math.PI ваш код выдает 3.14159265358979. В оба конца должно быть 3.1415926535897931.

Например, вот как вы можете сдвинуть десятичную точку в формате "r".

static string FormatMinDigits(double d)
{
    String r = d.ToString("r", System.Globalization.CultureInfo.InvariantCulture);
    if (Double.IsInfinity(d) || Double.IsNaN(d))
        return r;
    String us = r.TrimStart('-');
    int epos = us.IndexOf('E');
    string mantissa;
    int exponent;
    if (epos == -1)
    {
        mantissa = us;
        exponent = 0;
    }
    else
    {
        mantissa = us.Substring(0, epos);
        exponent = Int32.Parse(us.Substring(epos + 1));
    }
    int dotPos = mantissa.IndexOf('.');
    if (dotPos == -1)
        dotPos = mantissa.Length;
    mantissa = mantissa.Replace(".", "");
    string s;
    if (exponent > 0)
    {
        if (exponent + dotPos - mantissa.Length > 0)
            mantissa += new String('0', exponent + dotPos - mantissa.Length);
        s = mantissa.Insert(exponent + dotPos, ".").TrimEnd('.');
    }
    else if (exponent < 0)
    {
        if (-(exponent + dotPos) > 0)
            mantissa = new String('0', -(exponent + dotPos)) + mantissa;
        s = mantissa.Insert(0, "0.");
    }
    else
        s = mantissa.Insert(dotPos, ".").TrimEnd('.');
    if (d < 0)
        s = '-' + s;
    if (double.Parse(s, System.Globalization.CultureInfo.InvariantCulture) != d) // Since format "r", it should roundtrip.
        throw new Exception(string.Format("Internal error in FormatMinDigits: {0:r}", r));
    return s;
}
...