Hi
I have a float variable and would like to get only the part after the comma, so if I have 3.14. I would like to get 14 as an integer. How can I do that?
Hi
I have a float variable and would like to get only the part after the comma, so if I have 3.14. I would like to get 14 as an integer. How can I do that?
You can subtract the integer portion from the value itself to retrieve the fractional part.
float x = 3.14
float fractionalPortion = x - Math.Floor(x);
You can then multiply it to get the fractional part represented as an integer at whatever precision you'd like.
Mapping the fractional portion to an integer has some challenges - many floating point numbers cannot be represented as a base-10 integer, and thus may require more digits to represent than an integer can support.
Also, what of the case of numbers like 3.1 and 3.01? Mapping directly to an integer would both result in 1.
float x = 3.14
int fractionalPortionAsInt = (int) (100 * (x - Math.Floor(x)));
The cheating way to do it is:
private Int32 FractionalPart(double n)
{
string s = n.ToString("#.#########", System.Globalization.CultureInfo.InvariantCulture);
return Int32.Parse(s.Substring(s.IndexOf(".") + 1));
}
edit2: OK OK OK OK. Here is the most paranoid never fail version I can come up with. This will return the first 9 digits (or less, if there aren't that many) of the decimal portion of the floating point number. This is guaranteed to not overflow an Int32. We use the invariant culture so we know that we can use a period as the decimal separator.
To suggest something different than the others, an extension method (with a method similar to David's):
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();
Edit: I didn't use the "best" answer, because it omitted the hardest part, which is converting an arbitrary decimal number, and did not work for negative numbers. I added the correction requested in David's answer.
Here's the "noncheating" answer:
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;
We use precision instead of 0 to make up for the fact that floating point numbers don't work very well with decimal numbers. You can adjust it to suit your application. This is why I think the "cheating" string way is actually better.
Actually all solutions until now are wrong as they don't consider that using Math.Floor()
will do the wrong thing if the value is negative (e.g. 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));
Here's another version that also tells how many digits are part of the fractional make-up, which I needed.
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;
}
It's similar in idea to David's answer (his non-cheating version). However, I used the decimal type instead of double, which slows things down, but improves accuracy. If I convert David's (again, non-cheating version) answer to use a decimal type (in which case his "precision" variable can be changed to the constant zero), my answer runs about 25% faster. Note that I also changed his code to provide the number of fractional digits in my testing.
Try
float n = 3.14f;
int fractionalPart = new System.Version(n.ToString()).Minor;
David's "cheating version" answer doesn't seem to be very popular at the moment, but after looking into this for the better part of the day, I found the System.Version class. It has a constructor which takes a string. Using Reflector, I saw that it works by splitting the string into an array. I ran a test getting the fractional part of the arbitrary number 1234567891.1234567891m. With 1,000,000 iterations, it was 50% faster than the other answer I posted in spite of the fact that I first had to convert the decimal number to a string for the sake of the Version constructor. So David is getting a bad break when using a string conversion concept seems to be a bright way to go. Microsoft did.