获取十进制数字的整数和小数部分

时间:2018-12-26 06:20:26

标签: c# floating-point numbers

鉴于X.Y,我想得到XY

例如,给定123.456,我想得到123456 0.456)。

我可以执行以下操作:

decimal num = 123.456M;
decimal integer = Math.Truncate(num);
decimal fractional = num - Math.Truncate(num);    

// integer = 123
// fractional = 0.456   but I want 456

REF

但是,如上所述,使用这种方法我将得到0.456,而我需要456。当然,我可以执行以下操作:

int fractionalNums = (int)((num - Math.Truncate(num)) * 1000); 

// fracionalNums = 456

但是,此方法需要知道给定十进制数字有多少个小数,以便您可以乘以该数字(例如123.456有三个,123.4567有四个,123.456789有六个,123.1234567890123456789有19个。)

要考虑的几点:

  • 此操作将执行数百万次;因此,性能至关重要(也许基于位的解决方案会做得更好);
  • 精度至关重要,不能接受四舍五入。

注意1:

出于性能原因,我对任何基于字符串操作的方法都不感兴趣;请不要推荐这种方法。


注意2

我的问题中的数字为decimal类型,并且方法仅适用于decimal类型,并且在floatdouble上失败(由于浮点精度)是可以接受的。


注意3

小数点的两侧(即整数和小数部分)可以视为两个整数。因此,123.000456永远不会受到挑战,即使给出了挑战,也可以将其拆分为123456(因为双方都被视为整数)。

3 个答案:

答案 0 :(得分:4)

BitConverter.GetBytes(decimal.GetBits(num)[3])[2];-逗号后的位数

long[] tens = new long[] {1, 10, 100, 1000, ...};

decimal num = 123.456M;
int iPart = (int)num;
decimal dPart = num - iPart;
int count = BitConverter.GetBytes(decimal.GetBits(num)[3])[2];

long pow = tens[count];

Console.WriteLine(iPart);
Console.WriteLine((long)(dPart * pow));

答案 1 :(得分:1)

十进制的尾数为96位,因此 long 不足以获取所有可能的值。

定义为十进制定义的所有10(正)次幂:

decimal mults[] = {1M, 1e1M, 1e2M, 1e3M, <insert rest here>, 1e27M, 1e28M};

然后,在循环内部,您需要获取小数位数(将“尾数”除以10的幂乘以 以获得小数的标称值):

int[] bits = Decimal.GetBits(n);
int scale = (bits[3] >> 16) & 31;               // 567.1234 represented as 5671234 x 10^-4

decimal intPart = (int)n;                       // 567.1234 --> 567
decimal decPart = (n - intPart) * mults[scale]; // 567.1234 --> 0.1234 --> 1234

答案 2 :(得分:-1)

最简单的方法可能是将数字转换为字符串。 然后取小数点后的子串,再转回int。