Я имею переменную float и хотел бы получить только часть после запятой, поэтому, если у меня есть 3.14. Я хотел бы получить 14 как целое число. Как я могу это сделать?
С# получать цифры из переменной float
Ответ 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