У нас есть интересная проблема, были, мы должны определить десятичную точность пользовательского входа (текстовое поле). По существу мы должны знать количество вводимых десятичных разрядов и затем возвратить число точности, это лучше всего проиллюстрировано с примерами:
4 500 вводимых приведут к результату 1
4 500,1 вводимых приведут к результату 0.1
4 500,00 вводимых приведут к результату 0.01
4 500,450 вводимых приведут к результату 0.001
Мы думаем для работы со строкой, находя десятичный разделитель и затем вычисляя результат. Просто удивление, если существует более легкое решение этого.
Работать со строкой достаточно просто.
Если нет "." в строке верните 1.
Иначе верните «0.», за которым следует n-1 «0», за которым следует одна «1», где n - длина строки после десятичной точки.
Нет, более простого решения нет, нужно проверить строку. Если преобразовать «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
Если ваша мотивация в отслеживании точности ввода исключительно по причинам ввода и вывода, этого может быть достаточно для решения вашей проблемы.
Вот возможное решение с использованием строк;
static double GetPrecision(string s)
{
string[] splitNumber = s.Split('.');
if (splitNumber.Length > 1)
{
return 1 / Math.Pow(10, splitNumber[1].Length);
}
else
{
return 1;
}
}
Здесь есть вопрос; Calculate System.Decimal Precision and Scale, который, похоже, может представлять интерес, если вы захотите углубиться в эту тему.
Я думаю, вам следует просто сделать то, что вы предложили - использовать положение десятичной точки. Очевидным недостатком может быть то, что вам придется самому думать об интернационализации.
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()
и проверить возвращаемое значение. Возможно, алгоритм разбора сохраняет точность входных данных.
Наконец, я бы посоветовал не пытаться использовать числа с плавающей запятой. Простой разбор входных данных удалит любую информацию о нулях в конце. Поэтому вам придется добавлять искусственную ненулевую цифру, чтобы сохранить их, или делать подобные трюки. Вы можете столкнуться с проблемами точности. Наконец, найти точность на основе числа с плавающей запятой тоже не просто. Я вижу уродливую математику или цикл, умножающий на десять каждую итерацию, пока не останется ни одной дробной части. И цикл приходит с новыми проблемами точности...
UPDATE
Парсинг в десятичную дробь работает. Смотрите 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;