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


103

Мне нужно получить целое число слева от десятичной или двойной дроби. Например: мне нужно получить значение 4 из 4.6. Я пробовал использовать функцию Math.Floor, но она возвращает двойное значение, например: возвращает 4.0 из 4.6. В документации MSDN сказано, что он возвращает целочисленное значение. Я что-то упустил? Или есть другой способ достичь того, что я ищу?


2
В документации MSDN сказано, что он возвращает целочисленное значение . В документации MSDN указано, что Math.Floor возвращает System.Double, а не целое число.
широкополосный

Целочисленное значение действительно необходимо, но это не означает, что оно может храниться в виде типа «int» или «long». "Double" успешно сохраняет все целочисленные значения в гораздо более широком диапазоне, чем просто "int". Обратите внимание, что некоторые целочисленные значения могут быть округлены, если в части мантиссы недостаточно битов для хранения всех цифр целочисленного значения, когда его показатель степени с основанием 2 превышает 52: это округление целых значений в "double" может происходить для целых чисел больше 2 ^ 52 или меньше -2 ^ 52, но результатом все равно будет ближайшее представимое целое число; если вы используете «(длинный) этаж (x)», преобразование может быть в значительной степени неправильным.
verdy_p

Обратите внимание, однако, что допустимый диапазон целочисленных значений, которые могут быть представлены в "двойном", чрезвычайно велик, с абсолютными значениями до: (1 + (1-2 ^ -52)) × 2 ^ 1023 ≈ 1,7976931348623157E308; это намного больше чем 2 ^ 63-1 с "длинным". Однако диапазон целых чисел, которые могут быть сохранены отдельно, более ограничен, потому что «double» имеет только 52 бита для мантиссы (плюс 1 бит подразумевается для самого значимого бита, а не сохраняется), что означает, что «double» может хранить только целые числа ровно только тогда, когда их абсолютное значение меньше 2 ^ 53.
verdy_p

К сожалению, Math.Floor () не возвращает тип переменной «Number» внутри, используя «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
Floor возвращает целочисленное представление double и возвращает double для научных вычислений, этот ответ неверен, потому что double имеет 64 бита, а long также имеет 64 бита, но double не может хранить точные цифры младших значащих бит, даже если его можно сохранить правильно в длинном.
Акаш Кава

1
@Jon: почему вы не участвуете в бушующих дебатах о том, как сделать положительное число отрицательным в 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>, но приведение типов применяется только к соотношению, а не к результату продукта, и вы получите <code> 0 * Volume </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 Но в любом случае я попробую ваше предложение. Спасибо.

Что ж, правда, вверху написано «возвращает целое число», но тип указан под ним: public static double Floor (double d)
Нил Н.

3
integer! = int( answers.com/integer ) - целые числа могут храниться в Double(см. ответ Джона), и существует бесконечное количество целых чисел, которые не могут быть сохранены в int.
Shog9,

Шог, я не говорил, что не могут. Я сказал, что «это все еще TYPE Double»
Neil 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. Не приводите исходный double как int, потому что правила для пола другие (IIRC) для отрицательных чисел.


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

Это даст вам точное значение, которое вы хотите, если вы возьмете 4.6его 4как результат.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.