Чому Math.Floor (Double) повертає значення типу Double?


103

Мені потрібно отримати ціле ліве значення лівої сторони від десяткової або подвійної. Для Ex: мені потрібно отримати значення 4 від 4.6. Я спробував використовувати функцію Math.Floor, але вона повертає подвійне значення, наприклад: Повертає 4.0 з 4.6. Документація MSDN говорить, що вона повертає ціле значення. Я щось тут пропускаю? Або є інший спосіб досягти того, що я шукаю?


2
Документація MSDN говорить, що вона повертає ціле значення . У документації MSDN зазначено, що Math.Floor повертає System.Double, а не ціле число.
широкосмуговий

Ціле значення ефективно потрібне, але це не означає, що воно може зберігатися в "int" або "long". "Подвійний" успішно зберігає всі цілі значення в набагато ширшому діапазоні, ніж просто "int". Зауважте, що деякі цілі значення можуть бути округленими, коли частина мантіси не має достатньо бітів для зберігання всіх цифр цілого значення, коли його показник базис-2 вище 52: таке округлення цілих значень у "подвійному" може відбутися для цілих чисел, що перевищують 2 ^ 52 або нижче -2 ^ 52, але результат все одно буде найближчим цілим числом, який можна представити; якщо ви використовуєте "(довгий) поверх (x)", перетворення може бути значною мірою неправильним.
verdy_p

Зауважте, однак, що допустимий діапазон цілих чисел, які можуть бути представлені у "подвійному", надзвичайно великий, з абсолютними значеннями до: (1 + (1 - 2 ^ −52)) × 2 ^ 1023 ≈ 1.7976931348623157E308; це набагато більше 2 ^ 63-1 з "довгим". Однак діапазон цілих чисел, які можуть бути збережені чітко, є більш обмеженим, оскільки "подвійний" має лише 52 біти для мантіси (плюс 1 біт, що мається на увазі для найзначнішого біта, не зберігається), тобто "подвійний" може зберігати лише цілих чисел точно щойно, коли їх абсолютне значення нижче 2 ^ 53.
verdy_p

На жаль, Math.Floor () не повертає змінну типу "Число" внутрішньо, використовуючи "Long", якщо можливо, або "Double" в іншому випадку лише для великих округлих цілих чисел. І стандартна бібліотека Math не обробляє такий уніфікований тип змінної числа. Існують інші математичні бібліотеки, що реалізують уніфікований тип чисел, включаючи довгі, подвійні або великі цілі числа, закодовані в упакованих десяткових або двійкових, без втрати підтримуваного діапазону чи точності.
verdy_p

Відповіді:


146

Діапазон doubleзначно більший, ніж діапазон intабо long. Розглянемо цей код:

double d = 100000000000000000000d;
long x = Math.Floor(d); // Invalid in reality

Ціле число виходить за межі діапазону long- так що ви очікуєте, що це станеться?

Зазвичай ви знаєте, що значення насправді буде в межах intабо long, таким чином, ви додаєте його:

double d = 1000.1234d;
int x = (int) Math.Floor(d);

але тягарість для цієї ролі припадає на розробника, а не на Math.Floorсамого себе. Було б надмірно обмежувальним, щоб зробити його просто невдаче, за винятком усіх значень поза діапазону long.


2
Підлога повертає ціле представлення подвійного, і він повертає подвійне для наукових обчислень, ця відповідь не є правильною, оскільки у подвійного має 64 біти, а у довгого також 64 біта, але подвійний не може зберігати точні цифри нижчих значущих бітів, навіть якщо він може бути правильно збережений. в довгому.
Акаш Кава

1
@ Джон: як же ти не важив на дебати бушує над тим, як зробити позитивне число негативне в C #?: Stackoverflow.com/questions/1348080 / ...
MusiGenesis

3
@Jon: знайди час. Виявляється, спільнота виявила, що множення додатного числа на -1 зробить його негативним. На StackOverflow все добре.
MusiGenesis

1
@javapowered: Ні, (int) 15.0 не є 0. Щось інше пішло не так, але ми не можемо сказати, що з цього всього. Створіть коротку, але повну програму, яка демонструє це, а потім задайте питання. Я підозрюю, що вам буде важко відтворити ...
Джон Скіт

1
@MusiGenesis: <code> (int) IGNORE_RATIO * Volume </code> обчислюється як <code> (int) 0,15 * Volume </code>, але typecast застосовується лише до співвідношення, а не до результату продукту, і ви отримуєте <code> 0 * том </code>, тобто нуль! Використовуйте замість <code> (int) (IGNORE_RATIO * Volume) </code>, щоб вирішити ВАШ помилку.
verdy_p

11

Згідно з MSDN, Math.Floor (double) повертає подвійний: http://msdn.microsoft.com/en-us/library/e0b5f0xb.aspx

Якщо ви хочете це як int:

int result = (int)Math.Floor(yourVariable);

Я бачу, як стаття MSDN може вводити в оману, вони повинні були вказати, що хоча результат є "цілим числом" (в даному випадку означає ціле число), він все ще є TYPE Double


Дякую за вашу відповідь Насправді я дивився цю статтю: msdn.microsoft.com/en-us/library/e0b5f0xb.aspx Але все одно я спробую вашу пропозицію. Дякую.

Щоправда, вгорі він говорить "повертає ціле число", але тип вказаний під ним: загальнодоступний статичний подвійний поверх (подвійний d)
Neil N

3
integer! = int( answer.com/integer ) - цілі числа можуть зберігатися в Double(див. відповідь Йона), і існує нескінченна кількість цілих чисел, які не можуть бути збережені в int.
Shog9

Шог, я не сказав, що вони не могли. Що я сказав: "Це все-таки TYPE Double"
Ніл N

1
@Neil: правильно - просто хотів підкреслити різницю між "цілим числом" (назва набору) та int(ім'я типу).
Shog9

4

Якщо вам просто потрібна ціла частина числа, киньте це число на int. Це вріже число у десятковій точці.

double myDouble = 4.6;
int myInteger = (int)myDouble;

2
Важливо зауважити, що кастинг intповодиться інакше Floor, за від'ємних чисел. Floorзавжди скорочуватиметься до найвід’ємнішого числа, тоді як кастинг до intусікає до 0.
Магнус


0

Підлога залишає його як подвійний, щоб ви могли зробити більше подвійних розрахунків з ним. Якщо ви хочете це як int, виведіть результат floor як int. Не ставте початковий подвійний як int, оскільки правила для підлоги різні (IIRC) для від’ємних чисел.


0
Convert.ToInt32(Math.Floor(Convert.ToDouble(value)))

Це дасть точне значення того, що ви хочете, якби ви взяли 4.6це повертається 4як вихід.

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