Регулировка десятичной точности, .net - PullRequest
61 голосов
/ 15 июля 2009

Эти строки в C #

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

Итак, я вижу, что создание десятичной переменной из литерала позволяет мне контролировать точность.

  • Можно ли настроить точность десятичных переменных без использования литералов?
  • Как я могу создать б из а? Как я могу создать б из с?

Ответы [ 7 ]

49 голосов
/ 16 июля 2009

Такое сохранение нулей в конце было введено в .NET 1.1 для более строгого соответствия спецификации CLI ECMA.

На MSDN есть некоторая информация об этом, например, здесь .

Вы можете настроить точность следующим образом:

  • Math.Round (или Потолок, Пол и т. Д.) Для снижения точности (b от c)

  • Умножьте на 1.000 ... (с желаемым количеством десятичных знаков), чтобы увеличить точность - например, умножить на 1,0M, чтобы получить b из a.

18 голосов
/ 15 июля 2009

Вы просто видите разные представления одних и тех же данных. Точность 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, если применяется соответствующая строка формата.

6 голосов
/ 15 июля 2009
5 голосов
/ 26 августа 2009

Заманчиво путать decimal в SQL Server с decimal в .NET; они совершенно разные.

SQL Server decimal - это число с фиксированной запятой, точность и масштаб которого фиксируются при определении столбца или переменной.

.NET decimal - это число с плавающей точкой, например float и double (разница в том, что decimal точно сохраняет десятичные цифры, тогда как float и double точно сохраняют двоичные цифры). Попытки контролировать точность .NET decimal не имеют смысла, так как все вычисления будут давать одинаковые результаты независимо от наличия или отсутствия нулей заполнения.

5 голосов
/ 15 июля 2009

Я обнаружил, что могу «подделать» шкалу путем умножения или деления на фантазию 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;
1 голос
/ 09 января 2013

Это удалит все завершающие нули из десятичной дроби, а затем вы можете просто использовать ToString().

public static class DecimalExtensions
{
    public static Decimal Normalize(this Decimal value)
    {
        return value / 1.000000000000000000000000000000000m;
    }
}

Или, в качестве альтернативы, если вам нужно точное число конечных нулей, скажем, 5, сначала Normalize (), а затем умножьте на 1,00000 м.

1 голос
/ 15 июля 2009

Вопрос в том, действительно ли вам нужна точность , хранящаяся в десятичной дроби, а не просто отображение десятичной дроби с требуемой точностью. Большинство приложений знают, насколько они точны, и отображают их с таким уровнем точности. Например, даже если пользователь вводит счет-фактуру на 100 в пакете учетных записей, он все равно печатает как 100,00, используя что-то вроде val.ToString ("n2").

Как я могу создать б из а? Как я могу создать б из с?

возможно от c до b.

Console.WriteLine(Math.Round(2.00000000m, 1)) 

производит 2,0

от a до b сложно, поскольку концепция введения точности немного чужды математике.

Полагаю, ужасный хак может быть в оба конца.

decimal b = Decimal.Parse(a.ToString("#.0"));
Console.WriteLine(b);

производит 2,0

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...