假设我们有一个System.Decimal数。
为了说明,让我们拿一个ToString()表示如下:
d.ToString() = "123.4500"
以下可以说是关于这个十进制的。为了我们的目的,比例被定义为小数点右边的位数。有效比例是相似的,但忽略了在小数部分中出现的任何尾随零。 (换句话说,这些参数被定义为sql小数加上一些额外的参数来解释分数部分尾随零的System.Decimal概念。)
精准度:7
规模:4
> EffectivePrecision:5
> EffectiveScale:2
给定一个任意的System.Decimal,如何有效地计算所有这四个参数,而不转换为String并检查String?该解决方案可能需要Decimal.GetBits。
更多的例子:
Examples Precision Scale EffectivePrecision EffectiveScale 0 1 (?) 0 1 (?) 0 0.0 2 (?) 1 1 (?) 0 12.45 4 2 4 2 12.4500 6 4 4 2 770 3 0 3 0
(?)或者将这些精度解释为零将会很好。
解决方法
是的,你需要使用Decimal.GetBits。不幸的是,你必须使用一个96位整数,并且在.NET中没有简单的整数类型可以处理96位。另一方面,您可以使用十进制本身…
这里有一些与你的例子相同的代码。希望你觉得它有用 :)
using System; public class Test { static public void Main(string[] x) { ShowInfo(123.4500m); ShowInfo(0m); ShowInfo(0.0m); ShowInfo(12.45m); ShowInfo(12.4500m); ShowInfo(770m); } static void ShowInfo(decimal dec) { // We want the integer parts as uint // C# doesn't permit int[] to uint[] conversion,// but .NET does. This is somewhat evil... uint[] bits = (uint[])(object)decimal.GetBits(dec); decimal mantissa = (bits[2] * 4294967296m * 4294967296m) + (bits[1] * 4294967296m) + bits[0]; uint scale = (bits[3] >> 16) & 31; // Precision: number of times we can divide // by 10 before we get to 0 uint precision = 0; if (dec != 0m) { for (decimal tmp = mantissa; tmp >= 1; tmp /= 10) { precision++; } } else { // Handle zero differently. It's odd. precision = scale + 1; } uint trailingZeros = 0; for (decimal tmp = mantissa; tmp % 10m == 0 && trailingZeros < scale; tmp /= 10) { trailingZeros++; } Console.WriteLine("Example: {0}",dec); Console.WriteLine("Precision: {0}",precision); Console.WriteLine("Scale: {0}",scale); Console.WriteLine("EffectivePrecision: {0}",precision - trailingZeros); Console.WriteLine("EffectiveScale: {0}",scale - trailingZeros); Console.WriteLine(); } }