Определить десятичную точность входного числа - PullRequest
9 голосов
/ 19 июля 2010

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

Введенное значение

4500 даст результат 1
Ввод 4500,1 даст результат 0,1
Ввод 4500,00 даст результат 0,01
Введенный 4500.450 даст результат 0.001

Мы думаем поработать со строкой, найти десятичный разделитель и затем вычислить результат. Просто интересно, есть ли более простое решение для этого.

Ответы [ 7 ]

15 голосов
/ 19 июля 2010

Я думаю, вы должны просто сделать то, что вы предложили - использовать положение десятичной точки. Очевидный недостаток может заключаться в том, что вы должны самостоятельно подумать об интернационализации.

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

Разбор в десятичную систему. 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) прямо вперед.

11 голосов
/ 19 июля 2010

Просто интересно, есть ли проще решение этого.

номер

Использовать строку:

string[] res = inputstring.Split('.');
int precision = res[1].Length;
8 голосов
/ 19 июля 2010

Поскольку ваши последние примеры показывают, что конечные нули значимы, я бы исключил любое численное решение и пошел бы к строковым операциям.

3 голосов
/ 19 июля 2010

Нет, более простого решения нет, вам нужно изучить строку. Если вы преобразуете "4500" и "4500.00" в числа, они оба станут значением 4500, поэтому вы не сможете определить, сколько не значащих цифр было за десятичным разделителем.

2 голосов
/ 19 июля 2010

Интересно отметить, что 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 голос
/ 19 июля 2010

Вот возможное решение с использованием строк;

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

1 голос
/ 19 июля 2010

Работать со строкой достаточно просто.

Если "." Нетв строке верните 1.

В противном случае верните «0.», затем n-1 «0», а затем одну «1», где n - длина строки после десятичной точки.

...