Настройка десятичной точности,.net
Эти строки в С#
decimal a = 2m;
decimal b = 2.0m;
decimal c = 2.00000000m;
decimal d = 2.000000000000000000000000000m;
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
Console.WriteLine(d);
Создает этот вывод:
2
2.0
2.00000000
2.000000000000000000000000000
Итак, я вижу, что создание десятичной переменной из литерала позволяет мне контролировать точность.
- Могу ли я настроить точность десятичных переменных без использования литералов?
- Как я могу создать b из? Как я могу создать b из c?
Ответы
Ответ 1
Сохранение конечных нулей, подобных этому, было введено в .NET 1.1 для более строгого соответствия спецификации ECI CLI.
В MSDN есть некоторая информация об этом. здесь.
Вы можете настроить точность следующим образом:
-
Math.Round(или потолок, пол и т.д.) для уменьшения точности (b от c)
-
Умножьте на 1.000... (с количеством десятичных знаков, которые вы хотите), чтобы повысить точность - например. умножьте на 1.0M, чтобы получить b из.
Ответ 2
Вы просто видите разные представления одних и тех же данных. Точность decimal
будет масштабироваться так, чтобы она была (в пределах разумного).
Из System.Decimal
:
Десятичное число является плавающей точкой значение, которое состоит из знака, числовое значение, где каждая цифра в значение находится в диапазоне от 0 до 9, а a коэффициент масштабирования, который указывает положение плавающей десятичной точки который отделяет интеграл и дробные части числового значения.
Двоичное представление десятичной Значение состоит из 1-битового знака, 96-битное целочисленное число и масштабирование фактор, используемый для деления 96-битного целое число и указать, какая часть его является десятичной дробью. Масштабирование фактор неявно равен числу 10, повышен до уровня от 0 до 28. Следовательно, двоичный представление десятичного значения формы ((-2 96 до 2 96)/10 (от 0 до 28)), где -2 96 -1 равно MinValue и 2 96 -1 равно MaxValue.
Масштабный коэффициент также сохраняет любые конечные нули в десятичном числе. Конечные нули не влияют на значение десятичного числа в арифметические операции или операции сравнения. Однако конечные нули могут быть обнаруженный методом ToString, если соответствующая строка формата применяется.
Ответ 3
Как насчет
Math.Round(decimal d, int decimals)?
Ответ 4
Я обнаружил, что могу "подделать" шкалу умножением или делением на фантазию 1.
decimal a = 2m;
decimal c = 2.00000000m;
decimal PreciseOne = 1.000000000000000000000000000000m;
//add maximum trailing zeros to a
decimal x = a * PreciseOne;
//remove all trailing zeros from c
decimal y = c / PreciseOne;
Я могу изготовить достаточно точный 1 для изменения масштабных коэффициентов по известным размерам.
decimal scaleFactorBase = 1.0m;
decimal scaleFactor = 1m;
int scaleFactorSize = 3;
for (int i = 0; i < scaleFactorSize; i++)
{
scaleFactor *= scaleFactorBase;
}
decimal z = a * scaleFactor;
Ответ 5
Заманчиво путать decimal
в SQL Server с decimal
в .NET; они совершенно разные.
SQL Server decimal
- это номер фиксированной точки, точность и масштаб которого фиксируются при определении столбца или переменной.
.NET decimal
- это число с плавающей запятой, например float
и double
(разница в том, что decimal
точно сохраняет десятичные числа, тогда как float
и double
точно сохраняют двоичные цифры). Попытка контролировать точность .NET decimal
бессмысленна, поскольку все вычисления дают одинаковые результаты независимо от наличия или отсутствия нулей заполнения.
Ответ 6
Вопрос: действительно ли вам нужна точность хранится в десятичной форме, а не просто отображается десятичная цифра с требуемой точностью.
Большинство приложений знают внутренне, насколько точны они хотят быть и демонстрировать этот уровень точности. Например, даже если пользователь вводит счет-фактуру за 100 в пакете учетных записей, он все равно печатает как 100.00, используя что-то вроде val.ToString( "n2" ).
Как я могу создать b из? Как создать b из c?
c к b.
Console.WriteLine(Math.Round(2.00000000m, 1))
производит 2,0
a to b сложно, поскольку понятие введения точности немного чуждо математике.
Я думаю, что ужасный взлом может быть в оба конца.
decimal b = Decimal.Parse(a.ToString("#.0"));
Console.WriteLine(b);
производит 2,0
Ответ 7
Это приведет к удалению всех конечных нулей из десятичной дроби, а затем вы можете просто использовать ToString()
.
public static class DecimalExtensions
{
public static Decimal Normalize(this Decimal value)
{
return value / 1.000000000000000000000000000000000m;
}
}
Или, альтернативно, если вы хотите точное количество конечных нулей, скажем 5, сначала Normalize(), а затем умножьте на 1.00000 м.