Определить десятичную точность входного числа
У нас есть интересная проблема, где нам нужно определить десятичную точность ввода пользователя (текстовое поле). По сути, нам нужно знать количество введенных десятичных разрядов и затем возвращать точное значение, это лучше всего иллюстрировать примерами:
Введенные 4500 дадут результат 1
Введенный 4500,1 даст результат 0,1
Введенные 4500,00 дадут результат 0,01
Введенные 4500.450 дадут результат 0.001
Мы думаем поработать со строкой, найти десятичный разделитель и затем вычислить результат. Просто интересно, есть ли более простое решение для этого.
7 ответов
Я думаю, что вы должны просто сделать то, что вы предложили - использовать положение десятичной точки. Очевидным недостатком может быть то, что вы должны думать о интернационализации самостоятельно.
var decimalSeparator = NumberFormatInfo.CurrentInfo.CurrencyDecimalSeparator;
var position = input.IndexOf(decimalSeparator);
var precision = (position == -1) ? 0 : input.Length - position - 1;
// This may be quite unprecise.
var result = Math.Pow(0.1, precision);
Есть еще одна вещь, которую вы можете попробовать - Decimal
Тип хранит внутреннее значение точности. Поэтому вы могли бы использовать Decimal.TryParse()
и проверить возвращаемое значение. Возможно, алгоритм синтаксического анализа поддерживает точность ввода.
Наконец, я бы предложил не пытаться что-то использовать числа с плавающей запятой. Просто анализ входных данных удалит любую информацию о конечных нулях. Таким образом, вы должны добавить искусственную ненулевую цифру, чтобы сохранить их или делать подобные трюки. Вы можете столкнуться с проблемами точности. Наконец, найти точность на основе числа с плавающей запятой тоже непросто. Я вижу некрасивую математику или цикл, умножающийся на десять на каждой итерации, пока не останется никакой дробной части. И цикл идет с новыми проблемами точности...
ОБНОВИТЬ
Разбор в десятичную систему. Se Decimal.GetBits()
для деталей.
var input = "123.4560";
var number = Decimal.Parse(input);
// Will be 4.
var precision = (Decimal.GetBits(number)[3] >> 16) & 0x000000FF;
Отсюда с помощью Math.Pow(0.1, precision)
прямо вперед.
Просто интересно, есть ли более простое решение для этого.
Нет.
Используйте строку:
string[] res = inputstring.Split('.');
int precision = res[1].Length;
Поскольку ваши последние примеры показывают, что конечные нули значимы, я бы исключил любое числовое решение и пошел бы к строковым операциям.
Нет, более простого решения не существует, вы должны изучить строку. Если вы конвертируете "4500"
а также "4500.00"
к числам, они оба становятся ценностью 4500
так что вы не можете сказать, сколько не значащих цифр было позади десятичного разделителя.
Как интересно, Decimal
пытается сохранить точность, введенную пользователем. Например,
Console.WriteLine(5.0m);
Console.WriteLine(5.00m);
Console.WriteLine(Decimal.Parse("5.0"));
Console.WriteLine(Decimal.Parse("5.00"));
Имеет выход:
5.0
5.00
5.0
5.00
Если ваша мотивация в отслеживании точности ввода основана исключительно на причинах ввода и вывода, этого может быть достаточно для решения вашей проблемы.
Работать со строкой достаточно просто.
Если нет "." в строке верните 1.
В противном случае возвращается "0.", затем n-1 "0", за которым следует одна "1", где n - длина строки после десятичной точки.
Вот возможное решение с использованием строк;
static double GetPrecision(string s)
{
string[] splitNumber = s.Split('.');
if (splitNumber.Length > 1)
{
return 1 / Math.Pow(10, splitNumber[1].Length);
}
else
{
return 1;
}
}
Здесь есть вопрос; Рассчитайте System.Decimal Precision and Scale, который может быть интересен, если вы захотите углубиться в это.