Подтвердить что ты не робот

С# получать цифры из переменной float

Я имею переменную float и хотел бы получить только часть после запятой, поэтому, если у меня есть 3.14. Я хотел бы получить 14 как целое число. Как я могу это сделать?

4b9b3361

Ответ 1

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

    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. Вот самая параноидальная версия, которая никогда не выйдет из строя, которую я могу придумать. Это вернет первые 9 цифр (или меньше, если их не так много) десятичной части числа с плавающей запятой. Это гарантированно не переполняет Int32. Мы используем инвариантную культуру, поэтому знаем, что мы можем использовать период как десятичный разделитель.

Ответ 2

Вы можете вычесть целочисленную часть из самого значения для извлечения дробной части.

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

Затем вы можете размножить его, чтобы получить дробную часть, представленную как целое, любой ценой.

Сопоставление дробной части с целым числом имеет некоторые проблемы - многие числа с плавающей запятой не могут быть представлены как целое число-10, и, следовательно, может потребоваться больше цифр для представления, чем может поддерживать целое число.

Кроме того, что касается чисел чисел, таких как 3.1 и 3.01? Отображение непосредственно в целое число приведет к 1.

Ответ 3

Try

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

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

Ответ 4

Здесь другая версия, которая также показывает, сколько цифр является частью дробного макияжа, который мне нужен.

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, что замедляет работу, но повышает точность. Если я преобразую Дэвида (опять же, не читая версию), ответьте на использование десятичного типа (в этом случае его переменная "точность" может быть изменена на постоянный нуль), мой ответ работает примерно на 25% быстрее. Обратите внимание, что я также изменил его код, чтобы указать количество дробных цифр в моем тестировании.

Ответ 5

Вот ответ "нечего":

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 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 digit from n
    n -= digit;
}

// answer is in result;

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

Ответ 6

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

Ответ 7

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

Ответ 8

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

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: Я не использовал "лучший" ответ, потому что он пропустил самую сложную часть, которая преобразует произвольное десятичное число и не работает для отрицательных чисел. Я добавил исправление, запрошенное в ответе Дэвида.

Ответ 9

Это приведет к некоторым нечетным непредсказуемым значениям.

Числа с плавающей запятой не сохраняются как десятичные числа - экспоненциальная часть равна 2, а не 10.

Это означает, что некоторые числа (например, 1.1) не могут быть точно выражены как float (1.1 заканчивается чем-то вроде 1.099999999998)

Проблема в том, что для некоторых чисел стартовое число может не быть одним из них, в то время как десятичная часть сама по себе может быть.

Итак, ваш номер равен x.y

Вы получаете целочисленную часть x

Вы делаете x.y-x, чтобы получить 0.y

Иногда x.y может быть выражен как float и 0.y не может, поэтому вместо того, чтобы получить y, вы получите некоторое большое значение с большим количеством 0 или 9 в нем.

@David "обман" - это на самом деле лучший способ - в любом случае, он менее подвержен этой проблеме.

Однако я бы посмотрел, зачем вам это нужно - поплавки отлично подходят для очень быстрой математики, но немного мусор для точности. Если важна точность, используйте вместо этого тип decimal - этот тип гарантирует, что точное значение сохраняется, но за счет более медленной математики.

Ответ 10

На всякий случай кто-то хочет другой способ обмана:

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

где 100 используется, сдвиг десятичной части.

Ответ 11

с использованием регулярных выражений (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"

вы можете найти больше о Regex на http://www.regexr.com/

Математическое решение с использованием 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

Ответ 12

Я видел быстрый способ конвертировать float/doubles в целые числа, представляющие их цифры, используя битовую маску и метод GetBits... Он работает только в том случае, если результаты вписываются в 32-битное целое число, но оно по-прежнему действительно скользкое. Я не могу за это признаться, но посмотри:

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