C#从float变量中获取数字

我有一个浮点变量,只想得到逗号之后的部分,所以如果我有3.14。 我想得到14作为整数。 我怎样才能做到这一点?

欺骗的方式是:

private Int32 FractionalPart(double n) { string s = n.ToString("#.#########", System.Globalization.CultureInfo.InvariantCulture); return Int32.Parse(s.Substring(s.IndexOf(".") + 1)); } 

edit2:好的确定OK。 这是我能想到的最偏执的永不失败的版本。 这将返回浮点数的小数部分的前9位(或更少,如果没有那么多)。 这保证不会溢出Int32。 我们使用不变文化,因此我们知道我们可以使用句点作为小数分隔符。

您可以从值本身中减去整数部分以检索小数部分。

 float x = 3.14 float fractionalPortion = x - Math.Truncate(x); 

然后,您可以将其相乘以获得以您想要的任何精度表示为整数的小数部分。

将小数部分映射到整数具有一些挑战 – 许多浮点数不能表示为基数为10的整数,因此可能需要比整数可以支持的更多数字来表示。

另外,3.1和3.01这样的数字是什么情况? 直接映射到整数都会导致1。

尝试

 float n = 3.14f; int fractionalPart = new System.Version(n.ToString()).Minor; 

大卫的“作弊版本”答案目前似乎并不是很受欢迎,但在查看了当天的大部分时间后,我找到了System.Version类。 它有一个构造函数,它接受一个字符串。 使用Reflector,我看到它通过将字符串拆分成数组来工作。 我跑了一个测试得到任意数字1234567891.1234567891m的小数部分。 使用1,000,000次迭代, 它比我发布的其他答案快50%,尽管我首先必须为了Version构造函数将十进制数转换为字符串 。 因此,当使用字符串转换概念似乎是一个很好的方式时,David正在rest。 微软做到了。

这是另一个版本,它还告诉我需要多少位数是分数化妆的一部分。

 public static int GetFractionalPartAsInt(decimal n, out int numOfFractionalDigits) { n -= Math.Truncate(n); n = Math.Abs(n); int numOfFractionalDigitsValue = 0; // When n != Math.Truncate(n), we have seen all fractional decimals. while (n != Math.Truncate(n)) { n *= 10; numOfFractionalDigitsValue++; } numOfFractionalDigits = numOfFractionalDigitsValue; return (int)n; } 

这与David的回答(他的非作弊版本)的想法类似。 但是,我使用十进制类型而不是double,这会减慢速度,但会提高准确性。 如果我将David的(再次,非作弊版本)答案转换为使用十进制类型(在这种情况下,他的“精确”变量可以更改为常数零),我的答案运行速度提高了约25%。 请注意,我还更改了他的代码,以便在我的测试中提供小数位数。

这是“非che”的答案:

 double n = 3.14; const double precision = 0.000001; // we don't handle negative numbers very well if (n < 0) n = 0 - n; // remove the integer part of n n -= Math.Floor(n); int result = 0; while (n > precision) { // move 1/10th digit of n into 1's place n *= 10; // get that digit int digit = (int)Math.Floor(n); // shift result left and add digit to it result = result * 10 + digit; // remove 1's digit from n n -= digit; } // answer is in result; 

我们使用precision而不是0来弥补浮点数与十进制数不能很好地运行的事实。 您可以根据您的应用进行调整。 这就是为什么我认为“作弊”字符串方式实际上更好。

实际上到目前为止所有的解决方案都是错误的,因为他们不认为如果值为负,使用Math.Floor()会做错误的事情(例如Math.Floor(-2.8) – > -3)

 double number = -1234.56789; decimal numberM = Convert.ToDecimal(number); decimal fraction = Math.Abs(numberM - Math.Truncate(numberM)); int mantissa = Convert.ToInt32((double)fraction * Math.Pow(10, fraction.ToString().Length - 2)); 
 float x = 3.14 int fractionalPortionAsInt = (int) (100 * (x - Math.Floor(x))); 

建议不同于其他的东西,扩展方法(使用类似于David的方法):

 public static int GetDecimalAsInt(this float num) { string s = n.ToString(); int separator = s.IndexOf(System.Globalization.CultureInfo.CurrentUICulture.NumberFormat.NumberDecimalSeparator); return int.Parse(s.Substring(separator + 1)); } // Usage: float pi = 3.14; int digits = pi.GetDecimalAsInt(); 

编辑:我没有使用“最佳”答案,因为它省略了最难的部分,即转换任意十进制数,并且不适用于负数。 我在David的回答中加入了要求的更正。

这将导致一些奇怪的不可预测的值。

浮点数不存储为小数 – 指数部分是2的幂,而不是10。

这意味着某些数字(例如1.1)无法准确表达为float(1.1最终类似于1.099999999998)

问题是,对于某些数字,起始数字可能不是其中之一,而小数部分本身可能是。

所以你的号码是xy

你得到整数部分x

你做xy – x得到0.y

有时xy可以表示为浮点数而0.y不能表示,所以不是得到y你会得到一些大的值,其中有很多0或9。

@ David的’作弊’方式实际上是最好的方式 – 无论如何最不容易出现这个问题。

但是我会看看为什么你需要这样做 – 浮点数非常适合非常快速的数学运算,但对于准确性来说有点垃圾。 如果准确性很重要,则使用decimal类型 – 该类型保证存储精确值,但代价是数学较慢。

以防万一有人想要另一种作弊方式:

 float x = 5.2f; int decimalPart = Math.Round((x - Math.Truncate(x))*100) 

使用100移位小数部分。

使用正则表达式(REGEX)

 string input_decimal_number = "3.14"; var regex = new System.Text.RegularExpressions.Regex("(?<=[\\.])[0-9]+"); if (regex.IsMatch(input_decimal_number)) { string decimal_places = regex.Match(input_decimal_number).Value; } 

//输入:“3.14”
//输出:“14”

//输入:“2.50”
//输出:“50”

您可以在http://www.regexr.com/上找到有关Regex的更多信息。

使用Math.Truncate的数学解决方案

  var float_number = 12.345; var result = float_number - Math.Truncate(float_number); 

使用乘数[10是N的幂(例如10²或10³),其中N是小数位数]

  // multiplier is " 10 to the power of 'N'" where 'N' is the number // of decimal places int multiplier = 1000; double double_value = 12.345; int double_result = (int)((double_value - (int)double_value) * multiplier); 

//输出345

我看到了一种快速的方法,使用位掩码和GetBits方法将浮点数/双精度转换为代表其数字的整数…仅当结果适合32位整数时才有效,但它仍然非常光滑……我可以不要相信它,但看看:

http://stsdb.com/showthread.php?t=58&p=285&viewfull=1#post285