假设我们有一个 System.Decimal 数字。
为了便于说明,我们以 ToString() 表示如下:
d.ToString() = "123.4500"
关于这个 Decimal 可以说如下。出于我们的目的,比例被定义为小数点右侧的位数。有效标度类似,但忽略小数部分中出现的任何尾随零。 (换句话说,这些参数的定义类似于 SQL 小数加上一些附加参数来解释小数部分尾随零的 System.Decimal 概念。)
给定一个任意的 System.Decimal,如何有效地计算所有这四个参数,而不需要转换为字符串并检查字符串?该解决方案可能需要 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 位的简单整数类型。另一方面,您可以使用Decimal
本身...
下面是一些代码,它产生与您的示例相同的数字。希望你觉得它有用 :)
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();
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)