c# - 以数学方式确定小数值的精度和小数位数

标签 c# .net math decimal precision

我一直在寻找一些方法来确定 C# 中小数的小数位数和精度,这让我想到了几个 SO 问题,但它们似乎都没有正确答案,或者有误导性的标题(它们实际上是关于 SQL服务器或其他一些数据库,而不是 C#),或任何答案。我认为以下帖子最接近我所追求的内容,但即使这样似乎也是错误的:

Determine the decimal precision of an input number

首先,似乎对比例和精度之间的区别有些混淆。根据谷歌(根据 MSDN):

Precision is the number of digits in a number. Scale is the number of digits to the right of the decimal point in a number.

话虽如此,数字 12345.67890M 的比例为 5,精度为 10。我还没有发现可以在 C# 中准确计算这个数字的代码示例。

我想制作两个辅助方法,decimal.Scale()decimal.Precision(),以便通过以下单元测试:

[TestMethod]
public void ScaleAndPrecisionTest()
{
    //arrange 
    var number = 12345.67890M;

    //act
    var scale = number.Scale();
    var precision = number.Precision();

    //assert
    Assert.IsTrue(precision == 10);
    Assert.IsTrue(scale == 5);
}

但我还没有找到可以执行此操作的代码段,尽管有几个人建议使用 decimal.GetBits(),而其他人则表示,将其转换为字符串并进行解析。

在我看来,将其转换为字符串并进行解析是一个糟糕的想法,甚至不考虑小数点的本地化问题。然而,GetBits() 方法背后的数学原理对我来说就像希腊语。

谁能描述在 C# 中确定 decimal 值的小数位数和精度的计算是什么样的?

最佳答案

这是使用 GetBits() function 获得比例的方法:

decimal x = 12345.67890M;
int[] bits = decimal.GetBits(x);
byte scale = (byte) ((bits[3] >> 16) & 0x7F); 

我能想到的获得精度的最佳方法是删除小数点(即使用 Decimal Constructor 重建没有上述比例的十进制数)然后使用对数:

decimal x = 12345.67890M;
int[] bits = decimal.GetBits(x);
//We will use false for the sign (false =  positive), because we don't care about it.
//We will use 0 for the last argument instead of bits[3] to eliminate the fraction point.
decimal xx = new Decimal(bits[0], bits[1], bits[2], false, 0);
int precision = (int)Math.Floor(Math.Log10((double)xx)) + 1;

现在我们可以将它们放入扩展中:

public static class Extensions{
    public static int GetScale(this decimal value){
    if(value == 0)
            return 0;
    int[] bits = decimal.GetBits(value);
    return (int) ((bits[3] >> 16) & 0x7F); 
    }

    public static int GetPrecision(this decimal value){
    if(value == 0)
        return 0;
    int[] bits = decimal.GetBits(value);
    //We will use false for the sign (false =  positive), because we don't care about it.
    //We will use 0 for the last argument instead of bits[3] to eliminate the fraction point.
    decimal d = new Decimal(bits[0], bits[1], bits[2], false, 0);
    return (int)Math.Floor(Math.Log10((double)d)) + 1;
    }
}

这是一个 fiddle .

关于c# - 以数学方式确定小数值的精度和小数位数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33490408/

相关文章:

algorithm - 测试一个数字是否是斐波那契

c# - 将数据加载到松散耦合 View 及其 View 模型/模型中的 MVVM 策略

C# 类实例通讯

c# - .NET如何在单独的类/表单上捕获预先捕获的异常

c# - 文档光标的路径是什么?

C# 完美数练习

javascript - JQuery 事件在异步回发时不起作用,在第二次回发时修复,在第三次回发时中断

c# - 从数据库表中获取没有时间的日期

c# - 有时是,有时不是JSON错误:“没有为'System.String'类型定义无参数构造函数”

javascript - 二维中点绕原点的旋转收敛到 0