Я думаю, вам следует просто сделать то, что вы предложили, - использовать позицию десятичной точки. Очевидным недостатком может быть то, что вам придется самому думать об интернационализации.
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()
и проверить возвращаемое значение. Возможно, алгоритм синтаксического анализа поддерживает точность ввода.
Наконец, я бы посоветовал не пробовать использовать числа с плавающей запятой. Простой анализ ввода удалит любую информацию о конечных нулях. Поэтому вам нужно добавить искусственную ненулевую цифру, чтобы сохранить их, или проделать аналогичные трюки. Вы можете столкнуться с проблемами точности. Наконец, найти точность на основе числа с плавающей запятой тоже непросто. Я вижу какую-то уродливую математику или цикл, умножающийся на десять на каждой итерации, пока не исчезнет дробная часть. И цикл имеет новые проблемы с точностью ...
ОБНОВЛЕНИЕ
Разбор на десятичную дробь работает. Дополнительную информацию см. В 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)
просто.
ОБНОВЛЕНИЕ 2
Использование decimal.GetBits () выделит массив int[]
. Если вы хотите избежать распределения, вы можете использовать следующий вспомогательный метод, который использует явную структуру макета, чтобы получить масштаб непосредственно из десятичного значения:
static int GetScale(decimal d)
{
return new DecimalScale(d).Scale;
}
[StructLayout(LayoutKind.Explicit)]
struct DecimalScale
{
public DecimalScale(decimal value)
{
this = default;
this.d = value;
}
[FieldOffset(0)]
decimal d;
[FieldOffset(0)]
int flags;
public int Scale => (flags >> 16) & 0xff;
}
person
Daniel Brückner
schedule
19.07.2010