Получить десятичную часть от двойного

85

Я хочу получить число после десятичной точки в виде целого числа. Например, только 05 от 1.05 или от 2.50 только 50, а не 0.50

user1095549
источник
15
2,50 - это всего 2,5. Я полагаю, вы говорите о струнах.
Тим Шмелтер
3
Вы всегда возвращаете первые две цифры после запятой? Является ли ввести decimal, float, string, ...?
Грег
3
Пример использования имеет большое значение для получения качественных ответов в следующий раз.
tmesser
да, только две цифры, ввод десятичный
user1095549
4
Команда разработчиков C # должна быть смущена (и должна принять меры) из-за того, что эта очень распространенная операция не имеет единственной функции Math., такой как Math.DecimalPart (двойной x) или что-то в этом роде. Слишком много слов «вы пробовали это, вы думали об этом» для того, что многим из нас нужно делать часто.
philologon

Ответы:

-21

Обновленный ответ

Здесь я даю 3 подхода к одному и тому же.

[1] Математическое решение с использованием Math.Truncate

 var float_number = 12.345;
 var result = float_number - Math.Truncate(float_number);

// ввод: 1.05
// вывод: "0.050000000000000044"

// ввод: 10.2
// вывод: 0.19999999999999929

Если это не тот результат, которого вы ожидаете, вам необходимо изменить результат на желаемую форму (но вы можете снова выполнить некоторые манипуляции со строками).

[2] с использованием множителя [который равен 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

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

[3] с использованием «Регулярных выражений (REGEX)»

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

Если вы собираетесь выполнять строковые операции с десятичными знаками, это будет предпочтительнее

    string input_decimal_number = "1.50";
    var regex = new System.Text.RegularExpressions.Regex("(?<=[\\.])[0-9]+");
    if (regex.IsMatch(input_decimal_number))
    {
        string decimal_places = regex.Match(input_decimal_number).Value;
    }

// ввод: «1.05»
// вывод: «05»

// ввод: "2.50"
// вывод: "50"

// ввод: «0,0550»
// вывод: «0550»

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

Картик Кришна Байджу
источник
Будьте осторожны с ToString (), поскольку он не будет возвращать десятичных частей для целых чисел, то есть, если MyValue равно 3, MyValue.ToString () вернет «3», поэтому Split ('.') [1] выдаст. Подумайте о том, чтобы явно указать формат необходимого количества десятичных знаков: MyValue.ToString ("F2"). Split ('.') [1]
Alex Beynenson
7
Это решение примерно на два порядка медленнее, чем любое другое решение на этой странице, и на четыре порядка медленнее, чем мой собственный ответ.
tmesser
1
Это решение зависит от культуры. Например, для русского и английского-американского языков используются разные десятичные разделители (запятая и точка соответственно). Таким образом, этот код не будет работать при настройке других культур.
Юрий Щкатула
2
Это решение разбивается на .десятичный разделитель, который не всегда является десятичным разделителем (например, в Европе используется десятичный разделитель ,). Вы должны добавить, CultureInfo.Invariantчтобы сделать его международным. Хотя проще использовать x - Math.Truncate(x)и творить чудеса с этим результатом.
Abel
3
@Kiquenet Потому что это 7-я ревизия. Это был исходный ответ: stackoverflow.com/revisions/19374418/1
Манфред Радлвиммер,
199

лучший из лучших способов:

var floatNumber = 12.5523;

var x = floatNumber - Math.Truncate(floatNumber);

результат вы можете конвертировать, как хотите

matterai
источник
10
Это должен быть принятый ответ, математическое решение математического вопроса, без всей этой утомительной возни с манипуляциями со строками
johnc 01
20
Думаю, у этого решения есть «проблема». Если floatNumber был «10,2», переменная x будет иметь вид «0,19999999999999929». Даже если это сработает, как ожидалось, результат будет «0,2», а не «2».
Dherik
4
Значения @Dherik Float и Double всегда имеют небольшие ошибки при вычитании в последних нескольких десятичных разрядах. Вы не должны считать их значительными. Если вам действительно нужна такая точность, вы должны использовать тип Decimal. Если вы не можете переключиться на Decimal (или просто не хотите), вам следует как-то отслеживать ожидаемую точность и учитывать это в операциях сравнения. Обычно я использую 4 знака после запятой, но из этого могут быть исключения.
philologon
Из msdn.microsoft.com/en-us/library/… : «Поскольку некоторые числа не могут быть представлены точно как дробные двоичные значения, числа с плавающей запятой могут быть только приближенными к действительным числам»
philologon
1
Заключительный комментарий: использование Math.Truncate было намерением автора библиотеки Math для такого рода ситуаций. Ответ @Matterai должен быть принятым.
philologon
81
var decPlaces = (int)(((decimal)number % 1) * 100);

Это предполагает, что ваш номер имеет только два десятичных знака.

tmesser
источник
1
(318.40d % 1) * 100выходов 39.9999999999977, вы можете использовать приведение, чтобы обойти ошибку округления:var decPlaces = (int)(((decimal)number % 1) * 100);
orad
@orad Хороший прием - числа с плавающей запятой всегда имеют эти небольшие неточности, поэтому приведение их к типу довольно благоразумно, чтобы обеспечить согласованное поведение. Я обновлю свой ответ, хотя Маттераи все еще более технически правильный.
tmesser
27

Существует более чистое и более быстрое решение, чем подход Math.Truncate:

double frac = value % 1;
Holmexx
источник
7
примечание: для отрицательных значений это отрицательное значение : -12.34% 1 => -0.33999999999999986
Alex
16

Решение без проблемы округления:

double number = 10.20;
var first2DecimalPlaces = (int)(((decimal)number % 1) * 100);
Console.Write("{0:00}", first2DecimalPlaces);

Выходы: 20

Обратите внимание, если бы мы не преобразовали в десятичный формат, он бы выводил 19.

Также:

  • для 318.40выходов: 40(вместо39)
  • для 47.612345выходов: 61(вместо612345)
  • для 3.01выходов: 01(вместо 1)

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

Обновить:

Следующее также будет работать, если обработать его как строку (на основе ответа @ SearchForKnowledge).

10.2d.ToString("0.00", CultureInfo.InvariantCulture).Split('.')[1]

Затем вы можете использовать его Int32.Parseдля преобразования в int.

орад
источник
1
Недурно для
модников
Я использовал это ... 10.2d.ToString ("0.00", CultureInfo.InvariantCulture) .Split ('.') [1]
Ziggler
10

Лучший способ -

        double value = 10.567;
        int result = (int)((value - (int)value) * 100);
        Console.WriteLine(result);

Вывод -

56
Параг Мешрам
источник
2
Не тестировал, но у этого есть неточность смещения, не так ли?
mafu
Ибо 10.20он будет выводить 19. Смотрите мой ответ.
orad
9

Самый простой вариант, возможно, с Math.truncate ()

double value = 1.761
double decPart = value - Math.truncate(value)
Nilgiccas
источник
2

Думаю, эта ветка устаревает, но я не могу поверить, что никто не упомянул Math.Floor

//will always be .02 cents
(10.02m - System.Math.Floor(10.02m))
Hal9000
источник
Для супер ленивых:double fract(double x) { return x - System.Math.Floor(x); }
Фелипе Гутьеррес
1
var result = number.ToString().Split(System.Globalization.NumberDecimalSeparator)[2]

Возвращает его как строку (но вы всегда можете преобразовать ее обратно в int) и предполагает, что число имеет "." где-то.

Система не работает
источник
1
int last2digits = num - (int) ((double) (num /  100) * 100);
Redditmerc
источник
Вопрос в том, чтобы получить первые 2 десятичные цифры. Для числа 318.401567dваше решение выводит 0.401567где 40ожидается.
orad
0
    public static string FractionPart(this double instance)
    {
        var result = string.Empty;
        var ic = CultureInfo.InvariantCulture;
        var splits = instance.ToString(ic).Split(new[] { ic.NumberFormat.NumberDecimalSeparator }, StringSplitOptions.RemoveEmptyEntries);
        if (splits.Count() > 1)
        {
            result = splits[1];
        }
        return result;
    }
Береж
источник
0

Вот метод расширения, который я написал для аналогичной ситуации. Мое приложение получало числа в формате 2.3 или 3.11, где целочисленный компонент числа представлял годы, а дробный компонент - месяцы.

// Sample Usage
int years, months;
double test1 = 2.11;
test1.Split(out years, out months);
// years = 2 and months = 11

public static class DoubleExtensions
{
    public static void Split(this double number, out int years, out int months)
    {
        years = Convert.ToInt32(Math.Truncate(number));

        double tempMonths = Math.Round(number - years, 2);
        while ((tempMonths - Math.Floor(tempMonths)) > 0 && tempMonths != 0) tempMonths *= 10;
        months = Convert.ToInt32(tempMonths);
    }
}
Митч Стюарт
источник
0

Это может быть накладными расходами, но должно работать.

double yourDouble = 1.05;
string stringForm = yourDouble.ToString();
int dotPosition = stringForm.IndexOf(".");
decimal decimalPart = Decimal.Parse("0" + stringForm.Substring(dotPosition));

Console.WriteLine(decimalPart); // 0.05
Юсуфбек
источник
0
 string input = "0.55";
    var regex1 = new System.Text.RegularExpressions.Regex("(?<=[\\.])[0-9]+");
    if (regex1.IsMatch(input))
    {
        string dp= regex1.Match(input ).Value;
    }
Код
источник
1
Было бы здорово, если бы вы могли добавить описание того, как регулярное выражение помогает в решении проблемы
Клептус
-1

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

Рассмотрите возможность использования двойного _Doubleзначения 0.66781, следующий код будет показывать только числа после точки, .которые66781

double _Double = 0.66781; //Declare a new double with a value of 0.66781
string _Decimals = _Double.ToString().Remove(0, _Double.ToString().IndexOf(".") + 1); //Remove everything starting with index 0 and ending at the index of ([the dot .] + 1) 

Другое решение

Вы также можете использовать класс, Pathкоторый выполняет операции с экземплярами строк кроссплатформенным способом.

double _Double = 0.66781; //Declare a new double with a value of 0.66781
string Output = Path.GetExtension(D.ToString()).Replace(".",""); //Get (the dot and the content after the last dot available and replace the dot with nothing) as a new string object Output
//Do something
Программное обеспечение Picrofo
источник
-2

Используйте регулярное выражение: Regex.Match("\.(?\d+)")кто-нибудь поправит меня, если я ошибаюсь

мазки
источник
Не очень популярен, Regex.Matchно я получил следующую ошибку при попытке получить значение десятичной дробиArgumentException was unhandled: parsing "\.(?\d+)" - Unrecognized grouping construct.
Picrofo Software
-2

Это очень просто

       float moveWater =  Mathf.PingPong(theTime * speed, 100) * .015f;
       int    m = (int)(moveWater);
       float decimalPart= moveWater -m ;

       Debug.Log(decimalPart);
Чагатай Япыджы
источник
-2

Почему бы не использовать int y = value.Split('.')[1];?

Split()Функция разбивает значение в отдельный контент и 1выводит 2 - ое значение после.

SearchForKnowledge
источник
Это будет работать:Int32.Parse((12.05123d.ToString("0.00").Split('.')[1]))
orad
Потому что вы преобразуете его в строку, чтобы выполнять манипуляции со строкой. Не думаю, что вы понимаете, насколько это медленно и расточительно.
dmarra