Отримайте десяткову частину з подвійної


83

Я хочу отримати число після десяткової крапки у вигляді цілого числа. Наприклад, лише 05 з 1,05 або з 2,50 лише 50, а не 0,50


15
2,50 - це лише 2,5. Припускаю, ви говорите про струни.
Тім Шмельтер

3
Ви завжди повертаєте перші дві цифри після десяткової коми? Чи є ввести decimal, float, string, ...?
Грег

3
Приклад звичаїв має великий шлях до отримання якісних відповідей для наступного разу.
tmesser

так, лише дві цифри, введення десяткове
user1095549

3
Команда розробників C # повинна бути збентежена (і вжити заходів), що ця найпоширеніша операція не має єдиної Math.функції, такої як Math.DecimalPart (подвійний х) чи щось інше. Існує занадто багато «ти спробував це, чи думав ти про це» для чогось, що багатьом з нас потрібно робити часто.
філолог

Відповіді:


-20

Оновлена ​​відповідь

Тут я даю 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", тому розділить ('.') [1]. Подумайте про те, щоб чітко вказати формат на потрібну вам кількість десяткових знаків: MyValue.ToString ("F2"). Розділити ('.') [1]
Алекс Бейненсон,

7
Це рішення приблизно на два порядки повільніше, ніж будь-яке інше рішення на цій сторінці, і на чотири порядки повільніше, ніж моя власна відповідь.
tmesser

1
Це рішення є специфічним для культури. Наприклад, у російській та англійсько-американській мовах існують різні десяткові роздільники (кома та крапка відповідно). Тож цей код зазнає невдачі в інших культурах.
Yury Schkatula

2
Це рішення розділяється на ., який не завжди є десятковим роздільником (тобто в Європі десятковий роздільник є ,). Вам потрібно додати, CultureInfo.Invariantщоб зробити його міжнародним. Хоча простіше просто використовувати x - Math.Truncate(x)і робити магію на цьому результаті.
Абель

3
@Kiquenet, бо це вже 7-а редакція. Це був своєрідний відповідь: stackoverflow.com/revisions/19374418/1
Манфред Radlwimmer

196

найкращим із найкращих способів є:

var floatNumber = 12.5523;

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

результат ви можете конвертувати як завгодно


10
Це має бути прийнятою відповіддю, математичним рішенням математичного питання, без усього того нудного глузування в маніпулюванні
рядками

20
Я думаю, що це рішення має "проблему". Якщо floatNumber було "10,2", змінна x буде приблизно на зразок "0,19999999999999929". Навіть якщо це спрацює, як очікувалося, результат буде "0,2", а не "2".
Дерік,

4
Значення @Dherik Float та Double завжди мають невеликі помилки при відніманні в останні кілька знаків після коми. Ви не повинні розглядати їх як важливі. Якщо вам насправді потрібна така точність, вам слід використовувати десятковий тип. Якщо ви не можете перейти на десятковий (або просто не хочете), тоді вам слід якось відстежувати очікувану точність і враховувати це в операціях порівняння. Зазвичай я використовую 4 знаки після коми, але з цього можуть бути винятки.
філолог

З msdn.microsoft.com/en-us/library/… : "Оскільки деякі числа не можуть бути представлені точно як дробові двійкові значення, числа з плаваючою крапкою можуть наближати лише дійсні числа"
philologon

1
Остаточний коментар: Використання програми Math.Truncate було наміром авторської бібліотеки математики для подібної ситуації. Відповідь @Matterai має бути прийнятою.
філолог

80
var decPlaces = (int)(((decimal)number % 1) * 100);

Це передбачає, що ваше число має лише два знаки після коми.


(318.40d % 1) * 100виходи 39.9999999999977, ви можете використовувати кастинг, щоб обійти помилку округлення:var decPlaces = (int)(((decimal)number % 1) * 100);
orad

@orad Хороший дзвінок - номери з плаваючою комою завжди мають ці невеликі неточності, тому кастинг досить розумний, щоб забезпечити послідовну поведінку. Я оновлю свою відповідь, хоча відповідь Matterai все ще є більш технічно правильною.
tmesser

26

Існує більш чисте та швидше рішення, ніж підхід "Math.Truncate":

double frac = value % 1;

6
примітка: для від’ємних значень це від’ємне : -12,34% 1 => -0,3399999999999999986
Алекс Пока

15

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

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
Не тестував, але це страждає від неточності поплавця, ні?
мафу

Для 10.20нього буде виводитися 19. Дивіться мою відповідь.
орад

10

Найпростіший варіант, можливо, з Math.truncate ()

double value = 1.761
double decPart = value - Math.truncate(value)

2

Я думаю, ця тема старіє, але я не можу повірити, що ніхто не згадував Math.Floor

//will always be .02 cents
(10.02m - System.Math.Floor(10.02m))

Для супер ледачих: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);

Питання в тому, щоб отримати перші 2 десяткові цифри. Для числа 318.401567dвиведіть рішення, 0.401567де 40очікується.
орад

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
Було б чудово, якби ви могли додати опис того, як регулярний вираз допомагає вирішити проблему
Cleptus

-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

-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 - е значення після.


Це спрацює:Int32.Parse((12.05123d.ToString("0.00").Split('.')[1]))
orad

Оскільки ви перекидаєте його в рядок, щоб виконувати маніпуляції з рядками. Я не думаю, що ви усвідомлюєте, наскільки це повільно і марнотратно.
dmarra
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.