C#检查小数是否超过3位小数?

JK.*_*JK. 14 c# decimal

我有一种情况我无法改变:一个数据库表(表A)接受6个小数位,而另一个表(表B)中的相关列只有3个小数位.

我需要从A复制到B,但如果A的小数位数超过3,则额外数据将丢失.我无法更改表定义,但我可以添加一个解决方法.所以我试图找出如何检查小数是否超过3位小数?

例如

Table A
Id, Qty,  Unit(=6dp)
1,  1,     0.00025
2,  4000,  0.00025

Table B
Id, TotalQty(=3dp)
Run Code Online (Sandbox Code Playgroud)

我希望能够找出表A中的Qty*Unit是否超过3位小数(第1行会失败,第2行会通过):

if (CountDecimalPlaces(tableA.Qty * tableA.Unit) > 3)
{
    return false;
}
tableB.TotalQty = tableA.Qty * tableA.Unit;
Run Code Online (Sandbox Code Playgroud)

我该如何实现这个CountDecimalPlaces(decimal value) {}功能?

Rod*_*257 49

您可以将舍入到3位小数的数字值与原始值进行比较.

if (Decimal.Round(valueDecimal, 3) != valueDecimal)
{
   //Too many decimals
}
Run Code Online (Sandbox Code Playgroud)


car*_*ira 14

这适用于3位小数,它可以适用于通用解决方案:

static bool LessThan3DecimalPlaces(decimal dec)
{
    decimal value = dec * 1000;
    return value == Math.Floor(value);
}
static void Test()
{
    Console.WriteLine(LessThan3DecimalPlaces(1m * 0.00025m));
    Console.WriteLine(LessThan3DecimalPlaces(4000m * 0.00025m));
}
Run Code Online (Sandbox Code Playgroud)

对于一个真正的通用解决方案,您需要"解构"其部分中的十进制值 - 请查看Decimal.GetBits以获取更多信息.

更新:这是一个通用解决方案的简单实现,适用于整数部分小于long的所有小数.MaxValue(对于trully泛型函数,你需要类似"大整数"的东西).

static decimal CountDecimalPlaces(decimal dec)
{
    int[] bits = Decimal.GetBits(dec);
    int exponent = bits[3] >> 16;
    int result = exponent;
    long lowDecimal = bits[0] | (bits[1] >> 8);
    while ((lowDecimal % 10) == 0)
    {
        result--;
        lowDecimal /= 10;
    }

    return result;
}
static void Foo()
{
    Console.WriteLine(CountDecimalPlaces(1.6m));
    Console.WriteLine(CountDecimalPlaces(1.600m));
    Console.WriteLine(CountDecimalPlaces(decimal.MaxValue));
    Console.WriteLine(CountDecimalPlaces(1m * 0.00025m));
    Console.WriteLine(CountDecimalPlaces(4000m * 0.00025m));
}
Run Code Online (Sandbox Code Playgroud)

  • 如果使用dec == 0调用CountDecimalPlaces将创建一个无限循环 (6认同)

Phi*_*l M 6

将小数点后 3 位的数字乘以 10 的 3 次方将得到一个没有小数位的数字。当模数为整数时% 1 == 0。所以我想出了这个......

bool hasMoreThanNDecimals(decimal d, int n)
{
    return !(d * (decimal)Math.Pow(10, n) % 1 == 0);
}
Run Code Online (Sandbox Code Playgroud)

n当小于(不等于)小数位数时返回 true 。


Jas*_*ska 5

这是一个非常简单的单行代码,用于获取小数位数:

decimal myDecimal = 1.000000021300010000001m;
byte decimals = (byte)((Decimal.GetBits(myDecimal)[3] >> 16) & 0x7F);
Run Code Online (Sandbox Code Playgroud)