“减少” sql十进制数据类型最小精度和基于值的小数位数

发布于 2024-11-15 16:16:27 字数 820 浏览 0 评论 0原文

我正在解决一个涉及许多 sql 十进制乘法的问题,使用相当高的精度。

最近的一个错误促使我做了一些研究,我发现了一篇令人谦卑的文章(http://msdn.microsoft.com/en-us/library/ms190476.aspx)了解如何计算小数结果的精度和小数位。

据我了解,为了避免截断或意外舍入,有时需要将操作数和可能的中间计算转换为可以工作并给出所需结果的大小。 每个操作数都以十进制(19,5)的形式提供给我。我对此无能为力,因为我们支持如此广泛的价值观。

我的问题:我可以将这些十进制(19,5)值的类型“即时”减少/转换为可容纳该值的最小十进制类型(精度和小数位数)吗?

例如,我可以在将这个变量(@Cw)用于我的乘法之前“即时”将其转换为decimal(4,1​​)吗?

DECLARE @Cw decimal(19,5)
SET @Cw = 113.5

--Some type of CAST, i.e.
--CAST(@Cw as DECIMAL(GetActualPrecision(@Cw), GetActualScale(@Cw)))

-–should show 4 instead of 19
SELECT SQL_VARIANT_PROPERTY(@NewCw, 'Precision') 

–-should show 1 instead of 5
SELECT SQL_VARIANT_PROPERTY(@NewCw, 'Scale')

谢谢!

I’m working on a problem involving many sql decimal multiplications using a fairly high precision.

A recent bug prompted me to do some research, and I've come across a humbling article (http://msdn.microsoft.com/en-us/library/ms190476.aspx) on how the precision and scale of the decimal result are calculated.

It’s my understanding that in order to avoid truncation or unexpected rounding, it’s sometimes necessary to cast the operands and possibly the intermediate calculations to sizes that will work and give the desired results.
Each operand is given to me as a decimal(19,5). There’s nothing I can do about this since we support such a wide range of values.

My question: Can I reduce/cast the type of these decimal(19,5) values 'on-the-fly' to the smallest decimal type (precision and scale) that will hold the value?

For example, can I cast this variable (@Cw) to a decimal(4,1) 'on-the-fly' before it will get used in my multiplication?

DECLARE @Cw decimal(19,5)
SET @Cw = 113.5

--Some type of CAST, i.e.
--CAST(@Cw as DECIMAL(GetActualPrecision(@Cw), GetActualScale(@Cw)))

-–should show 4 instead of 19
SELECT SQL_VARIANT_PROPERTY(@NewCw, 'Precision') 

–-should show 1 instead of 5
SELECT SQL_VARIANT_PROPERTY(@NewCw, 'Scale')

Thanks!

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

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

发布评论

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

评论(2

只怪假的太真实 2024-11-22 16:16:27

没有动态 CAST:比例和精度是静态的:“定点”
如果你想要任意精度,请使用 float,这当然是“浮点”,

我们主要使用十进制,没有任何问题。

如果你有复杂的数学,但效果不太好,那么我会考虑在 SQL 中使用 CLR 或在具有更好库的客户端代码中进行

No

There is no dynamic CAST: scale and precision are static: "fixed point"
If you want arbritrary precision use float which is of course "floating point"

We use decimal mostly and don't have any issues.

If you have complex maths that doesn't work too well then I'd consider using CLR in SQL or doing it in client code which has better libraries

非要怀念 2024-11-22 16:16:27

我遇到了同样的问题,我使用 CLR 解决了它。以下 C# 函数将十进制类型“打包”为尽可能小的精度和小数位数。

internal static SqlDecimal PackPrecScale(SqlDecimal d)
{
    //Remove leading zeros
    var s = d.ToString();
    var l = s.Length;
    var indexofperiod = s.IndexOf('.');

    //Remove trailing zeros
    if (indexofperiod != -1)
    {
        while (s[l - 1] == '0') l--;
        if (s[l - 1] == '.')
        {
            l--;
            indexofperiod = -1;
        }
    }

    var precision = 6;
    var scale = 0;
    if (l > 0)
    {
        precision = l;
        if (s[0] == '-') precision--;
        if (indexofperiod != -1)
        {
            precision--;
            scale = l - indexofperiod - 1;
        }
        if (precision < 6) precision = 6;
    }

    return SqlDecimal.ConvertToPrecScale(d, precision, scale);
}

I had the same issue and I solved it using CLR. The following C# function "packs" the decimal type to the smallest possible precision and scale.

internal static SqlDecimal PackPrecScale(SqlDecimal d)
{
    //Remove leading zeros
    var s = d.ToString();
    var l = s.Length;
    var indexofperiod = s.IndexOf('.');

    //Remove trailing zeros
    if (indexofperiod != -1)
    {
        while (s[l - 1] == '0') l--;
        if (s[l - 1] == '.')
        {
            l--;
            indexofperiod = -1;
        }
    }

    var precision = 6;
    var scale = 0;
    if (l > 0)
    {
        precision = l;
        if (s[0] == '-') precision--;
        if (indexofperiod != -1)
        {
            precision--;
            scale = l - indexofperiod - 1;
        }
        if (precision < 6) precision = 6;
    }

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