Почему Math.floor возвращает двойной?


104

Официальный Javadoc говорит, что Math.floor()возвращает double"равное математическому целому числу", но почему тогда не должно возвращать int?

Ответы:


80

Согласно тому же Javadoc:

Если аргумент равен NaNлибо бесконечности, либо положительному нулю, либо отрицательному нулю, результат будет таким же, как и аргумент. Этого нельзя сделать с файлом int.

Самое большое doubleзначение также больше самого большого int, поэтому оно должно быть a long.


41
кажется несовместимым с функциями Math.Round, которые действительно возвращают int / long и по-другому обрабатывают особые случаи.
zod

1
Обратите внимание, что в Javadoc говорится, что он возвращает «наибольшее (ближайшее к положительной бесконечности) * значение с плавающей запятой *, которое меньше или равно аргументу и равно математическому целому числу» . Дано значение x> 2 ^ 53 , которое не будет таким же, как значение с усеченной дробной частью. Он вполне может быть немного меньше этого.
Джим Гаррисон

16

Это для точности. Тип данных double имеет 53-битную мантиссу. Среди прочего, это означает, что число типа double может представлять все целое до 2 ^ 53 без потери точности.

Если вы сохраните такое большое число в виде целого числа, вы получите переполнение. Целые числа имеют всего 32 бита.

Возврат целого числа в виде двойного числа является правильным здесь, потому что он предлагает гораздо более широкий полезный диапазон чисел, чем целое число.


Конечно, он мог бы долго справляться с такими ценностями. Однако вам все равно придется решить, что делать с удвоениями> 2 ^ 63.
Джон Скит,

1
@Jon, правда, но это повлияет на производительность (нет инструкции по преобразованию из длинных в двойные ни в одном известном мне наборе инструкций). Интересно, что Math.floor делает с двойными> 2 ^ 53 в первую очередь. Некоторые результаты невозможно представить.
Нильс Пипенбринк,

Но тогда псевдоидиоматическая форма (int) Math.floor (foo), которая также встречается в официальном javadoc, небезопасна, поскольку результат может не соответствовать int, я прав? И опять же, какая форма безопасного использования Math.floor, если результат может не уместиться даже в long?
Raibaz 05

10

Другие объяснили вам, почему, я расскажу вам, как правильно округлить, если вы хотите это сделать. Если вы собираетесь использовать только положительные числа, вы можете использовать этот оператор:

int a=(int) 1.5;

Однако (int) всегда округляется до 0. Таким образом, если вы хотите сделать отрицательное число:

int a=(int) -1.5; //Equal to -1

В моем случае я не хотел этого делать. Я использовал следующий код для округления, и, похоже, он хорошо справляется со всеми крайними случаями:

private static long floor(double a)
{
    return (int) Math.floor(a);
}

7
Почему бы не использовать (int) Math.floor(a)? Наверное, это эффективнее и короче.
Соломон Учко

@Solomon Ucko вместо (int) Math.floor(a)вы можете просто написать (int) a, если a положительное.
Лев Леонтьев

3

Что бы вы хотели вернуть, если бы дали ему вдвое больше, чем наибольшее int или long?

(По общему признанию, если он больше самого большого long, точность в любом случае будет низкой - это может быть не ближайшее теоретическое целое число, но даже в этом случае ...)


0

Так же, как в Java есть целочисленное деление и деление с плавающей запятой, существуют целочисленные и плавающие способы делать пол:

double f = Math.floor(x);

или

int k = (int) x; 

но вам всегда нужно быть осторожным с использованием floor с арифметикой конечной точности: ваш расчет x может дать что-то вроде 1.99999999, которое будет равно 1, а не 2 обеими формами. Существует множество алгоритмов, которые необходимо обойти это ограничение, чтобы избежать получения неверных результатов для некоторых входных значений.


0

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

Например, если вы введете Not a Number (NaN) в Math.floor, он передаст его.

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

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