Парсим string to float без экспоненты в C#
Ситуация простейшая, но именно на ней я застрял.
Есть следующий метод, конвертирующий строку в float?
public static float? ToSingleNullable(string value)
{
if (string.IsNullOrEmpty(value))
return null;
else
{
float number = 0;
if (float.TryParse(value, out number))
return number;
return null;
}
}
В ситуации, когда на входе приходит что-то больше 19 999 999, то float.TryParse вместо, скажем, 20 000 012 выводит 2e+6 или где-то там. При обратной конвертации в лучшем случае получаю 20 000 010. Причём предсказать, что получится - 20 000 000 или 20 000 010 не могу.
В общем, как сделать так, чтобы вот текущий метод возвращал число с плавающей точкой именно в десятичной записи?
В сети куча примеров для .ToString(), а вот с обратной конвертацией пусто. Сменить на decimal не выйдет - метод должен вернуть именно float.
Строку вводит пользователь в человеческом виде. То есть грубо говоря получается такое:
string str = "20100999";
float number = ToSingleNullable(str);
Console.WriteLine(number);//условно 2е+6
Ответы (1 шт):
Для начала, упростим ваш метод до следующего:
public static float? ToSingleNullable(string value)
{
if (float.TryParse(value, out float number))
return number;
return null;
}
Теперь немного теории.
Вещественные числа имеют некоторую точность. Она не может быть бесконечной, потому что тогда потребуется бесконечное количество памяти для хранения одного числа. Соответственно, неизбежно часть данных теряется.
float f = 20100999;
Console.WriteLine(f); // 2,0101E+07
Console.WriteLine(f.ToString("F0")); // 20101000
Из этого примера следует, что значение 20100999 невозможно точно представить в виде вещественного числа одинарной точности.
Следовательно, если вы хотите получить представление числа в определённом виде, то нужно задать желаемый формат: Standard numeric format strings, Custom numeric format strings.
Я использовал формат F с указанием спецификатора точности: 0 десятичных знаков.
string str = "20100999";
float? number = ToSingleNullable(str);
Console.WriteLine(number.Value.ToString("F0")); // 20101000
Дополню. У числа в двоичном виде нет никакого формата. Это просто набор нолей и единиц.
float f = 20100999;
var bytes = BitConverter.GetBytes(f);
foreach (byte b in bytes)
Console.Write(Convert.ToString(b, 2) + " ");
Console.WriteLine();
Результат:
11000100 1011011 10011001 1001011
Это и есть искомое число в памяти компьютера. А экспоненциальная форма она только для нас, для людей. Мы можем эти биты вывести в разных удобных для нас представлениях.