Найкращий спосіб отримати ціле число з десяткового числа


90

Який найкращий спосіб повернути цілу числову частину десяткової коми (у c #)? (Це має спрацювати для дуже великих чисел, які можуть не вписуватися в int).

GetIntPart(343564564.4342) >> 343564564
GetIntPart(-323489.32) >> -323489
GetIntPart(324) >> 324

Метою цього є: я вставляю в десяткове поле (30,4) в базі даних і хочу переконатись, що я не намагаюся вставити число, яке є занадто довгим для поля. Визначення довжини цілочисельної частини десяткової є частиною цієї операції.


Ви не можете отримати частину int; Ви можете отримати цілу числову частину і скинути дробову частину. Ціла числова частина десяткового дробу може легко переповнювати int, або кидати, або обертати, мовчки вбиваючи ваш код.

1
Ну, тому це питання не таке просте, як здається. Мені потрібно, щоб це працювало для дуже великих чисел так само надійно, як і для малих чисел. Однак "ціле число" є більш точним, ніж "int" - я переформулюю вище.
Яков Еліс

Відповіді:


213

До речі, хлопці, (int) Decimal.MaxValue переповнюватиметься. Ви не можете отримати десяткову частину "int", оскільки десяткова цифра занадто велика, щоб її можна було помістити у поле int. Щойно перевірив ... навіть довго занадто великий (Int64).

Якщо ви хочете, щоб біт десяткового значення був ЗЛІВО крапки, вам потрібно зробити це:

Math.Truncate(number)

і поверніть значення як ... ДЕСЯТНИЧНИЙ або ДВОЙНИЙ.

редагувати: Зрізати - це точно правильна функція!


Отже, результат є десятковим або подвійним, що ніколи не матиме нічого після точки, але немає вбудованого об'єкта для зберігання результату як "int" (без десяткових знаків), який здається трохи кульгавим?
Купс

@CodeBlend: Існує не так багато вимог до проектування фреймворків навколо бажання втратити точність.

@CodeBlend: Ви все одно втратите точність, оскільки відсікаєте десяткові значення числа. Не впевнений, на що ви заходите.

Не впевнений, що це спрацює чи ні. Тому що Math.Truncate (-5.99999999999999999) повертає мені -6.0 ... !!
Бхарат Морі,

@Bharat Mori: Здається, -5,9999999999999999999 округляється до -6,0 перед усіканням. Спробуйте із суфіксом "m", і це спрацює. Math.Truncate (-5,9999999999999999999m) дає -5.
Генрі


4

Залежить від того, що ви робите.

Наприклад:

//bankers' rounding - midpoint goes to nearest even
GetIntPart(2.5) >> 2
GetIntPart(5.5) >> 6
GetIntPart(-6.5) >> -6

або

//arithmetic rounding - midpoint goes away from zero
GetIntPart(2.5) >> 3
GetIntPart(5.5) >> 6
GetIntPart(-6.5) >> -7

За замовчуванням завжди використовується перше, що може бути несподіванкою, але має дуже добрий сенс .

Ваш явний акторський склад буде робити:

int intPart = (int)343564564.5
// intPart will be 343564564

int intPart = (int)343564565.5
// intPart will be 343564566

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

Я б зробив:

Math.Floor(Math.Abs(number));

Також перевірте розмір вашого decimal- вони можуть бути досить великими, тому вам, можливо, доведеться використовувати a long.


(довгий) Decimal.MaxValue переповнюється.

Справедливий момент - я думаю, саме тому Math.Truncate (десятковий) повертає десятковий.
Кіт

У C # кастинг на int не округляється, тому (int) 0.6f буде 0, а (int) 343564565.5 закінчиться через 5, а не 6. Спробуйте тут: repl.it/repls/LuxuriousCheerfulDistributeddatabase
sschmidTU

0

Вам просто потрібно кинути його як таку:

int intPart = (int)343564564.4342

Якщо ви все-таки хочете використовувати його як десятковий знак для подальших обчислень, тоді функцією, яку ви хочете, є Math.Truncate (або, можливо, Math.Floor, якщо ви хочете певної поведінки для від’ємних чисел).


5
Це неправильно неправильно неправильно. Якщо результат перевищує те, що може вмістити Int32, він або викине виняток, або (ще гірше !!!) мовчки переллється і обернеться назад, даючи вам абсолютно неправильний результат, навіть не знаючи про це.

2
Ні, це не неправильно . Багато з них не є дійсними для дуже великих знаків після коми / з плаваючою комою, але це чудово для більшості ситуацій. Числа дуже часто обмежуються достатньо низькими при кодуванні, тому це не повинно бути проблемою. Крім того, я надав рішення Math.Truncate, яке працює для всіх значень.
Noldorin

2
Я розумію, чому ти на мене злишся. Справа в тому, що ваша відповідь неправильна. Ви кажете йому, щоб він ризикнув, не розбившись, бо, привіт, багато цифр мало. Це дурний ризик. Вам слід відредагувати свою відповідь і видалити все, крім математики.

1
Ви знаєте, що вони говорять про ASSUME. Крім того, ваше припущення є особливо жахливим. Це запально? Думаю, ви могли б так сказати. Ви також можете сказати, що сказати комусь робити щось дурне, що спричинить за собою проблеми в дорозі, також є запальним, якщо не сказати неетичним.

1
Дійсно, це було б неправильно, якби я мав намір дати оманливу відповідь. Як би там не було, я просто намагався допомогти. Якщо я винен у незначному непорозумінні або не в повній мірі оцінив питання, це досить справедливо - це не злочин. То чому ми зараз сперечаємось? Ми всі погоджуємось, що Truncate - це правильна відповідь.
Noldorin

0

Дуже простий спосіб відокремити значення та його часткову часткову вартість.

double  d = 3.5;
int i = (int)d;
string s = d.ToString();
s = s.Replace(i + ".", "");

s - дробова частина = 5, а
i - ціле число = 3


1
Дивіться верхню відповідь вище. Це не працює, оскільки (int)Decimal.MaxValueпереповнюється.
Яков Еліс

0

Я сподіваюся вам допомогти.

/// <summary>
/// Get the integer part of any decimal number passed trough a string 
/// </summary>
/// <param name="decimalNumber">String passed</param>
/// <returns>teh integer part , 0 in case of error</returns>
private int GetIntPart(String decimalNumber)
{
    if(!Decimal.TryParse(decimalNumber, NumberStyles.Any , new CultureInfo("en-US"), out decimal dn))
    {
        MessageBox.Show("String " + decimalNumber + " is not in corret format", "GetIntPart", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return default(int);
    } 

    return Convert.ToInt32(Decimal.Truncate(dn));
}

-2
   Public Function getWholeNumber(number As Decimal) As Integer
    Dim round = Math.Round(number, 0)
    If round > number Then
        Return round - 1
    Else
        Return round
    End If
End Function

1
Прийнята відповідь, розміщена понад вісім років тому, пояснює, чому ця відповідь неправильна. Діапазон decimalнабагато більший, ніж у int. Крім того, це не питання VB.
Джо Фаррелл,

@JoeFarrell - якщо ви вважаєте, що відповідь неправильна, ви можете подумати про її зменшення, на додаток до того, щоб просто залишити коментар. Однак не позначайте його (не те, що я кажу, що у вас є). Це спроба відповісти на питання. Це може бути неправильною мовою, може бути неправильно навіть у VB, але це спроба. Дивіться, наприклад, " Коли відповідь відповідає на неправильне запитання, це не відповідь? ".
Wai Ha Lee
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.