C # получить цифры из переменной с плавающей точкой

Я согласен с ответом от zacherates.

Но вы можете сделать вызов intern () в ваших нелиберальных строках.

Из примера zacherates:

// ... but they are not the same object
new String("test") == "test" ==> false 

Если вы ставите нелитеральное равенство строки, это правда

new String("test").intern() == "test" ==> true 
13
задан Karsten 24 June 2009 в 20:15
поделиться

8 ответов

Обманчивый способ сделать это:

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

edit2: ОК ОК ОК ОК. Вот самая параноидальная версия, которую я могу придумать. Это вернет первые 9 цифр (или меньше, если их не так много) десятичной части числа с плавающей запятой. Это гарантированно не приведет к переполнению Int32. Мы используем инвариантную культуру, поэтому знаем, что можем использовать точку в качестве десятичного разделителя.

6
ответ дан 1 December 2019 в 06:10
поделиться

На самом деле все решения до сих пор ошибочны, поскольку они не считают, что использование 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));
1
ответ дан 1 December 2019 в 06:10
поделиться

Вот ответ "без читинга":

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;

Мы используем точность вместо 0, чтобы компенсировать тот факт, что числа с плавающей запятой не очень хорошо работают с десятичными числами. Вы можете настроить его в соответствии с вашим приложением. Вот почему я думаю, что "обман" струнный способ на самом деле лучше.

2
ответ дан 1 December 2019 в 06:10
поделиться
float x = 3.14
int fractionalPortionAsInt = (int) (100 * (x - Math.Floor(x)));
0
ответ дан 1 December 2019 в 06:10
поделиться

Чтобы предложить что-то отличное от других, метод расширения (с методом, похожим на метод Дэвида):

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();

Изменить: Я не использовал «лучший» ответ, потому что он опустил самую сложную часть, которая заключается в преобразовании произвольного десятичного числа, и не работал с отрицательными числами. Я добавил исправление, запрошенное в ответе Дэвида.

0
ответ дан 1 December 2019 в 06:10
поделиться

You can subtract the integer portion from the value itself to retrieve the fractional part.

float x = 3.14
float fractionalPortion = x - Math.Truncate(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.

35
ответ дан 1 December 2019 в 06:10
поделиться

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.

2
ответ дан 1 December 2019 в 06:10
поделиться

Попробуйте

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

ответ Дэвида "читерская версия", похоже, не очень популярен в момент, но, изучив это большую часть дня, я нашел класс System.Version. У него есть конструктор, который принимает строку. Используя Reflector, я увидел, что он работает, разбивая строку на массив. Я провел тест, получив дробную часть произвольного числа 1234567891.1234567891m. После 1000000 итераций он был на 50% быстрее, чем другой ответ, который я опубликовал, несмотря на то, что мне сначала пришлось преобразовать десятичное число в строку ради конструктора версии. Так что у Дэвида плохая передышка, когда использование концепции преобразования строк кажется оптимальным решением. Microsoft сделала.

8
ответ дан 1 December 2019 в 06:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: