C#从float变量中获取数字

时间:2009-06-24 20:15:55

标签: c# .net floating-point

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

12 个答案:

答案 0 :(得分:35)

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

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

然后你可以将它乘以得到的小数部分以你想要的任何精度表示为整数。

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

此外,3.1和3.01等数字的情况如何?直接映射到整数都会产生1。

答案 1 :(得分:8)

尝试

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

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

答案 2 :(得分:6)

这样做的作弊方式是:

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

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

答案 3 :(得分:2)

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

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;
}

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

答案 4 :(得分:1)

这是“非作弊”的答案:

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来弥补浮点数对十进制数不能很好的效果。您可以根据您的应用进行调整。这就是为什么我认为“作弊”字符串方式实际上更好。

答案 5 :(得分:1)

实际上到目前为止所有解决方案都是错误的,因为他们不认为如果值为负,使用Math.Floor()会做错事(例如Math.Floor(-2.8) - &gt; -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));

答案 6 :(得分:0)

float x = 3.14
int fractionalPortionAsInt = (int) (100 * (x - Math.Floor(x)));

答案 7 :(得分:0)

建议与其他人不同的东西,一种扩展方法(使用类似于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();

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

答案 8 :(得分:0)

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

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

这意味着某些数字(例如1.1)无法准确表达为float(1.1最终会像1.099999999998那样)

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

所以你的号码是x.y

你得到整数部分x

你做x.y - x得到0.y

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

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

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

答案 9 :(得分:0)

以防万一有人想要另一种欺骗方式:

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

其中100用于移动小数部分。

答案 10 :(得分:0)

使用正则表达式(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/

上找到有关正则表达式的更多信息

使用Math.Truncate

的数学解决方案
 var float_number = 12.345;
 var result = float_number - Math.Truncate(float_number);

使用乘数[乘以N的幂为10(例如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

答案 11 :(得分:-1)

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

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