소수점 이하 자릿수를 찾는 가장 좋은 솔루션 중 하나는 burning_LEGION의 게시물에 나와 있습니다.
여기에 STSdb 포럼 기사의 일부를 사용하고 있습니다 . 소수점 이하 자릿수 .
MSDN에서 다음 설명을 읽을 수 있습니다.
"10 진수는 부호, 값의 각 숫자 범위가 0에서 9 사이 인 숫자 값, 정수와 소수를 구분하는 부동 소수점의 위치를 나타내는 배율 인수로 구성된 부동 소수점 값입니다. 숫자 값의 일부. "
그리고 또한:
"Decimal 값의 이진 표현은 1 비트 부호, 96 비트 정수 및 96 비트 정수를 나누고 소수 부분을 지정하는 데 사용되는 배율 인수로 구성됩니다. 배율 인수는 다음과 같습니다. 암시 적으로 숫자 10, 0에서 28까지의 지수로 올렸습니다. "
내부 수준에서 10 진수 값은 4 개의 정수 값으로 표시됩니다.
내부 표현을 얻기 위해 공개적으로 사용 가능한 GetBits 함수가 있습니다. 이 함수는 int [] 배열을 반환합니다.
[__DynamicallyInvokable]
public static int[] GetBits(decimal d)
{
return new int[] { d.lo, d.mid, d.hi, d.flags };
}
반환 된 배열의 네 번째 요소에는 배율 인수와 부호가 포함됩니다. 그리고 MSDN에서 배율 인수는 암시 적으로 숫자 10이며 0에서 28까지의 지수로 올립니다. 이것이 바로 우리가 필요로하는 것입니다.
따라서 위의 모든 조사를 기반으로 우리는 방법을 구성 할 수 있습니다.
private const int SIGN_MASK = ~Int32.MinValue;
public static int GetDigits4(decimal value)
{
return (Decimal.GetBits(value)[3] & SIGN_MASK) >> 16;
}
여기서 SIGN_MASK는 부호를 무시하는 데 사용됩니다. 논리적이고 실제 스케일 팩터를 받기 위해 오른쪽으로 16 비트로 결과를 이동했습니다. 마지막으로이 값은 소수점 이하 자릿수를 나타냅니다.
여기서 MSDN은 배율 인수가 Decimal 숫자의 후행 0도 유지한다고 말합니다. 후행 0은 산술 또는 비교 연산에서 십진수 값에 영향을주지 않습니다. 그러나 적절한 형식 문자열이 적용되면 ToString 메서드에서 후행 0이 표시 될 수 있습니다.
이 솔루션은 최고의 솔루션처럼 보이지만 더 많은 것이 있습니다. 으로 C #에서 개인 방법에 접근 우리는 플래그 필드에 직접 액세스를 구축하고 int 배열을 구성 피하기 위해 표현식을 사용할 수 있습니다 :
public delegate int GetDigitsDelegate(ref Decimal value);
public class DecimalHelper
{
public static readonly DecimalHelper Instance = new DecimalHelper();
public readonly GetDigitsDelegate GetDigits;
public readonly Expression<GetDigitsDelegate> GetDigitsLambda;
public DecimalHelper()
{
GetDigitsLambda = CreateGetDigitsMethod();
GetDigits = GetDigitsLambda.Compile();
}
private Expression<GetDigitsDelegate> CreateGetDigitsMethod()
{
var value = Expression.Parameter(typeof(Decimal).MakeByRefType(), "value");
var digits = Expression.RightShift(
Expression.And(Expression.Field(value, "flags"), Expression.Constant(~Int32.MinValue, typeof(int))),
Expression.Constant(16, typeof(int)));
return Expression.Lambda<GetDigitsDelegate>(digits, value);
}
}
이 컴파일 된 코드는 GetDigits 필드에 할당됩니다. 함수는 10 진수 값을 ref로 수신하므로 실제 복사가 수행되지 않고 값에 대한 참조 만 수행됩니다. DecimalHelper에서 GetDigits 함수를 사용하는 것은 쉽습니다.
decimal value = 3.14159m;
int digits = DecimalHelper.Instance.GetDigits(ref value);
소수점 이하 자릿수를 구하는 가장 빠른 방법입니다.