Определить десятичную точность входного числа

У нас есть интересная проблема, где нам нужно определить десятичную точность ввода пользователя (текстовое поле). По сути, нам нужно знать количество введенных десятичных разрядов и затем возвращать точное значение, это лучше всего иллюстрировать примерами:

Введенные 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, который может быть интересен, если вы захотите углубиться в это.

Другие вопросы по тегам