派生小数类型 - 固定精度

发布于 2024-10-09 05:31:45 字数 586 浏览 4 评论 0原文

.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

如果你给每个会计师都会吃掉你的壁炉她之类的东西。

如果在这里加税,问题就会进一步加剧。

因此,不要存储尽可能多的小数并尽可能晚地四舍五入。创建一个类,使其在财务上正确并尽快将其四舍五入/截断存储。

Is there a way in .NET to create a type derived from decimal that would be used as a currency, so it rounds the arithmetic operations to the desired number of decimal points.

If not, what are the best practice for it in .NET?

EDIT (motivation):

Let's say I have a price:

125.00 Rep$

and I sell 0.25 pieces of it, that amounts to 31.25

Now, I have a discount of 15%, and to calculate discount and present it in absolute value I'll have:

31.25 * .85 = 26.5625

If I use other way:

31.25 * .15 = 4.6875

If I let some 3rd party control to truncate it and display it, for example, I could have:

26.56 +
 4.68 =
-----
31.24

And every accountant will eat your hearth if you give her something like that.

Add tax here, and problem multiplies further.

So, NO storing as much decimals and rounding it as late as possible. Create a class that will do it financially correct and store it as soon as possible rounded/truncated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

半夏半凉 2024-10-16 05:31:45

您当然不能创建从 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
    }
}

显然这里还需要更多 - 特别是您需要重写 GetHashCodeEquals,实现 IEquatable等等)

这绝对是你想要的吗?我认为更常见的是在中间操作期间保持尽可能多的精度,并且只在最后一刻进行舍入,例如存储在数据库中或显示给用户。

You certainly can't create a type derived from decimal, as it's a struct - and you can't create subtypes of structs.

You could create your own Currency struct which contained a decimal, though. You'd want to overload all the arithmetic operators to basically perform the arithmetic on the contained decimal values and then round appropriately.

For example:

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
    }
}

(Obviously there's a lot more needed here - in particular you'll want to override GetHashCode and Equals, implement IEquatable<T> etc.)

Is this definitely what you want though? I thought it was more common to keep as much precision as you could during intermediate operations, and only round at the last moment, e.g. for storage in a database or display to a user.

剪不断理还乱 2024-10-16 05:31:45

您提出的建议不能直接完成(从诸如 decimal 之类的值类型派生)。这也不是一个好主意,因为每次算术运算后的舍入都会给最终结果带来越来越大的误差。

如果我理解正确,您想要实现的目标最好通过正常使用 decimal 来完成,并在最后使用 System.Math.Round 一次 用于四舍五入。

What you propose cannot be done directly (deriving from a value type like decimal). It is also not a good idea, since rounding after every arithmetic operation will introduce larger and larger errors into the final result.

If I understand correctly, what you want to achieve is best done by using decimal normally, and using System.Math.Round once, at the end for rounding.

风吹短裙飘 2024-10-16 05:31:45

System.Decimal should already have what you need, if you use the: The Currency ("C") Format Specifier to output a decimal value.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文