Усечение и приведение к int из ceiled double

При выполнении std::ceil для двойного значения значение будет округлено до целого числа. Таким образом, 3.3 станет 4.0. Который может быть приведен или усечен до int. Что «отрежет» часть после запятой. Так:

int foo = (int)std::ceil(3.3);

Так что на первый взгляд это будет хранить 4 в foo. Однако двойное число является значением с плавающей запятой. Так что это может быть либо 4.000000001, либо 3.999999999. Последний будет усечен до 3.

Но на практике я никогда не видел, чтобы такое поведение происходило. Могу ли я с уверенностью предположить, что любая реализация вернет 4? Или это только IEEE-754 делает это. Или мне просто повезло?


person laurisvr    schedule 07.07.2015    source источник
comment
«Однако двойное число — это значение с плавающей запятой. Так что это может быть либо 4.000000001, либо 3.999999999. «Нет, это 4. Правда.   -  person Pascal Cuoq    schedule 07.07.2015
comment
@PascalCuoq: легко забыть, что относительно небольшие целые числа гарантированно сохраняются без потерь. Я только что сделал! Ваша короткая записка напомнила мне об этом. Пожалуйста, расширьте его немного и сделайте его ответом.   -  person quetzalcoatl    schedule 07.07.2015
comment
Аналогичный связанный вопрос, но не повторяющийся: "title="гарантирует ли ieee 754 float double и quad точное представление 2 1"> stackoverflow.com/questions/20029443/   -  person quetzalcoatl    schedule 07.07.2015
comment
@quetzalcoatl Я не знал об этой гарантии :). Но значит ли это, что усечение может «не сработать» для целых чисел, превышающих мантисса? В конце концов, мантисса двойного числа может быть меньше, чем целое длинное.   -  person laurisvr    schedule 07.07.2015


Ответы (2)


Округление (или ограничение) двойника всегда, всегда, всегда будет точным.

Для чисел с плавающей запятой ниже 2^(m+1), где m — количество мантиссальных битов, все целые числа имеют точное представление, поэтому результат может быть точно представлен.

Для чисел с плавающей запятой выше 2^(m+1)... они уже являются целыми числами. Имеет смысл, если подумать: не хватает битов мантиссы, чтобы растянуться справа от десятичной точки. Итак, снова округление/потолок точно.

person Sneftel    schedule 07.07.2015

ceil в C++ ведет себя так же, как и в C, где стандарт говорит

Функции ceil вычисляют наименьшее целочисленное значение не меньше x.

Результатом ceil всегда является представление целого числа с плавающей запятой; однако результат может переполнить целочисленный тип при усечении.

В вашем конкретном случае std::ceil(3.3) должно быть ровно 4.0, так как это "наименьшее целочисленное значение не менее" 3.3.

person molbdnilo    schedule 07.07.2015
comment
Что вы подразумеваете под результатом всегда целое число? Результат функции ceil? И чем целое число, хранящееся в двойном, отличается от нецелого числа? - person laurisvr; 07.07.2015
comment
@laurisvr Да. Добавил некоторые уточнения. - person molbdnilo; 07.07.2015
comment
Ах, теперь я понимаю, что вы имеете в виду :). Однако это не отвечает на мой первоначальный вопрос. Поскольку целочисленное значение по-прежнему хранится в двойном - person laurisvr; 07.07.2015
comment
@laurisvr Я не понимаю, как это не отвечает на ваш вопрос, но добавил некоторые дополнительные разъяснения. - person molbdnilo; 07.07.2015