Вывод десятичных типов - фиксированная точность - PullRequest
2 голосов
/ 24 декабря 2010

Есть ли в .NET способ создать тип, производный от десятичного числа, который будет использоваться в качестве валюты, поэтому он округляет арифметические операции до нужного количества десятичных знаков.

Если нет, то какиелучшая практика для этого в .NET?

РЕДАКТИРОВАТЬ (мотивация):

Допустим, у меня есть цена:

125.00 Rep$

, и я продаю 0.25 кускиэто, что составляет 31.25

Теперь у меня есть скидка 15%, и для расчета скидки и представления ее в абсолютном значении у меня будет:

31.25 * .85 = 26.5625

Если яиспользуйте другой способ:

31.25 * .15 = 4.6875

Если я позволю стороннему контролю обрезать его и отобразить, например, у меня может быть:

26.56 +
 4.68 =
-----
31.24

И каждый бухгалтер съест ваше очагесли вы дадите ей что-то в этом роде.

Добавьте сюда налог, и проблема умножится еще больше.

Итак, НЕТ хранить столько десятичных знаков и округлять их как можно позже.Создайте класс, который сделает это с финансовой точки зрения, и сохраните его как можно скорее округленным / усеченным.

Ответы [ 3 ]

3 голосов
/ 24 декабря 2010

Вы, конечно, не можете создать тип, производный от decimal, так как это структура - и вы не можете создавать подтипы структур.

Вы можете создать свою собственную Currency структуру, которая содержит десятичную дробь. Вы хотели бы перегрузить все арифметические операторы, чтобы в основном выполнить арифметику с содержащимися десятичными значениями, а затем округлить соответствующим образом.

Например:

public struct Currency
{
    private readonly decimal value;

    public Currency(decimal value)
    {
        this.value = decimal.Round(value, 2);
    }

    public override string ToString()
    {
        return value.ToString();
    }

    public static Currency operator+(Currency left, Currency right)
    {
        return new Currency(left.value + right.value);
    }

    public static Currency operator-(Currency left, Currency right)
    {
        return new Currency(left.value - right.value);
    }

    public static Currency operator/(Currency left, int right)
    {
        return new Currency(left.value / right);
    }
}

class Test
{
    static void Main()
    {
        Currency currency = new Currency(15);
        Console.WriteLine(currency / 10); // Prints 1.5
        Console.WriteLine(currency / 100); // Prints 0.15
        Console.WriteLine(currency / 1000); // Prints 0.2
    }
}

(Очевидно, здесь нужно гораздо больше - в частности, вы захотите переопределить GetHashCode и Equals, реализовать IEquatable<T> и т. Д.)

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

1 голос
/ 24 декабря 2010

То, что вы предлагаете, не может быть сделано напрямую (производное от типа значения, такого как decimal).Это также не очень хорошая идея, поскольку округление после каждой арифметической операции приведет к появлению все больших и больших ошибок в конечном результате.

Если я правильно понимаю, то, чего вы хотите достичь, лучше всего сделать, используя decimal обычнои используя System.Math.Round один раз, в конце для округления.

0 голосов
/ 24 декабря 2010

System.Decimal уже должен иметь то, что вам нужно, если вы используете: Спецификатор формата валюты ("C") для вывода десятичного значения.

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