Подтвердить что ты не робот

Что происходит в С++, когда целочисленный тип применяется к типу с плавающей запятой или наоборот?

Будут ли базовые биты просто "переинтерпретироваться" как значение с плавающей запятой? Или существует преобразование времени выполнения для получения ближайшего значения с плавающей запятой?

Является ли концом значение на каких-либо платформах (т.е. суждение поплавков отличается от ints)?

Как ведут себя разные типы ширины (например, int to float vs. int to double)?

Что стандарт языка гарантирует безопасность таких приводов/конверсий? Под броском я имею в виду статический_cast или C-стиль.

Как насчет инверсного преобразования float в int (или double to int)? Если поплавок имеет значение малой величины (например, 2), имеет ли бит шаблон одинаковый смысл при интерпретации как int?

4b9b3361

Ответ 1

Будут ли базовые биты просто "переинтерпретироваться" как значение с плавающей запятой?

Нет, значение преобразуется в соответствии с правилами в стандарте.

существует ли временное преобразование для получения ближайшего значения с плавающей запятой?

Да, есть время выполнения.

Для с плавающей запятой → integer значение усекается при условии, что исходное значение находится в диапазоне целочисленного типа. Если это не так, поведение undefined. По крайней мере, я думаю, что это имеет значение исходное значение, а не результат. Я должен был бы все посмотреть, чтобы быть уверенным. Граничный случай, если целевой тип char, скажем, будет CHAR_MAX + 0.5. Я думаю, что undefined использовать это для char, но, как я уже сказал, я не уверен.

Для целочисленной → с плавающей запятой результат - это то же самое значение, если это возможно, или же одно из двух значений с плавающей запятой с любой стороны целочисленного значения. Не обязательно ближе к ним.

Является ли контенция фактором на каких-либо платформах (т.е. суждение поплавков отличается от ints)?

Нет, никогда. Конверсии определяются в терминах значений, а не в представлениях хранения.

Как ведут себя разные типы ширины (например, int to float vs. int для удвоения)?

Все, что имеет значение, - это диапазоны и уточнения типов. Предполагая, что 32-битные int и IEEE 32-битные float, возможно, что int- > float-преобразование будет неточным. Предполагая также, что 64-разрядный IEEE-удваивается, невозможно, чтобы int- > double conversion было неточным, поскольку все значения int могут быть точно представлены как double.

Что стандарт языка гарантирует безопасность таких приводов/конверсий? Под литой, я имею в виду статический_cast или C-стиль.

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

Если float имеет значение малой величины (например, 2), имеет ли бит-шаблон то же значение при интерпретации как int?

Нет, это не так. 32-битное представление IEEE 2 равно 0x40000000.

Ответ 2

Для справки, это то, что говорит ИСО-МЭК 14882-2003.

4.9 Преобразования с плавающим интегралом

Значение типа с плавающей точкой r может быть преобразовано в rvalue целочисленного типа. Преобразование усекает; т.е. дробная часть отбрасывается. Поведение undefined, если усеченное значение не может быть представлено в целевом типе. [Примечание. Если тип назначения - `bool, см. 4.12. ]

Значение целочисленного типа или типа перечисления может быть преобразовано в r-значение типа с плавающей точкой. Результат является точным, если это возможно. В противном случае это определенный реализацией выбор либо следующего более низкого, либо более высокого представляемого значения. [Примечание: потеря точности происходит, если интегральное значение не может быть представлено точно как значение плавающего типа. ] Если тип источника bool, значение false преобразуется в ноль, а значение true преобразуется в один.

Ссылка: Что каждый компьютерный ученый должен знать о арифметике с плавающей точкой

Другие высоко ценные ссылки на тему быстрых преобразований float в int:

Хорошо прочитайте!

Ответ 3

Обычно выполняются преобразования во время выполнения, поскольку представления бит обычно не совместимы (за исключением того, что двоичный код 0 обычно равен 0 и 0.0). Стандарты C и С++ имеют дело только со значением, а не с представлением, и указывают на общепринятое поведение. Помните, что большое значение int обычно не будет точно представлено в float, а большое значение float не может быть представлено int.

Таким образом:

Все преобразования - это значения, а не битовые шаблоны. Не беспокойтесь о битовых шаблонах.

Не беспокойтесь о контенте, так как это вопрос поразрядного представления.

Преобразование int в float может потерять точность, если целочисленное значение велико по абсолютной величине; он менее вероятен с double, так как double является более точным и может представлять гораздо более точные числа. (Детали зависят от того, какие представления фактически использует система.)

Определения языка не говорят о битовых шаблонах.

Преобразование из float в int также зависит от значений, а не от битовых шаблонов. Точная версия с плавающей запятой 2.0 преобразуется в интеграл 2, потому что то, как создается реализация, а не из-за битовых шаблонов.

Ответ 4

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

Когда вы конвертируете float в int, вы выполняете операцию floor(). поэтому он просто сбрасывает биты после десятичной дроби

Для получения дополнительной информации о чтении с плавающей точкой: http://www.lahey.com/float.htm

Формат одиночной точности IEEE имеет 24 бита мантиссы, 8 бит экспоненты и бит знака. Внутренние регистры с плавающей запятой в микропроцессорах Intel, таких как Pentium, имеют 64 бита мантиссы, 15 бит экспоненты и бит знака. Это позволяет выполнять промежуточные вычисления с гораздо меньшей потерей точности, чем многие другие реализации. Нижняя сторона этого заключается в том, что в зависимости от того, как промежуточные значения хранятся в регистрах, вычисления, которые выглядят одинаково, могут дать разные результаты.

Итак, если ваше целое использует более 24 бит (исключая скрытый ведущий бит), тогда вы, вероятно, потеряете некоторую точность преобразования.

Ответ 5

переосмыслил? Термин "реинтерпретация" обычно относится к реинтерпретации необработанной памяти. Разумеется, невозможно достоверно переосмыслить целочисленное значение как значение с плавающей запятой (и наоборот), так как их физические представления обычно совершенно разные.

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

При преобразовании целочисленного значения в тип с плавающей запятой исходное значение преобразуется точно, если оно может быть представлено точно целевым типом. В противном случае значение будет изменено процессом преобразования.

Когда вы конвертируете значение с плавающей запятой в целочисленный тип, дробная часть просто отбрасывается (т.е. не выполняется ближайшее значение, но число округляется до нуля). Если результат не вписывается в целевой целочисленный тип, поведение undefined.

Обратите также внимание, что конверсии с плавающей запятой и целыми числами (и наоборот) являются стандартными преобразованиями и формально не требуют явного литья. Иногда люди могут использовать явное приведение для подавления предупреждений компилятора.

Ответ 6

Если вы произведете это значение, оно будет преобразовано (поэтому при преобразовании float → int 3.14 становится 3).

Но если вы нажмете указатель, вы фактически "переосмыслите" базовые бит. Поэтому, если вы сделаете что-то вроде этого:

double d = 3.14;
int x = *reinterpret_cast<int *>(&d);

x будет иметь "случайное" значение, основанное на представлении с плавающей запятой.

Ответ 7

Преобразование FP в интегральный тип нетривиально и даже не определено полностью.

Обычно ваш FPU реализует аппаратную инструкцию для преобразования из формата IEEE в int. Эта команда может принимать параметры (реализованные в аппаратном обеспечении), контролирующие округление. Ваш ABI, вероятно, указывает от раунда до ближайшего-ровного. Если вы используете X86 + SSE, он "вероятно, не слишком медленный", но я не могу найти ссылку с одним поиском Google.

Как и у любого FP, есть угловые случаи. Было бы неплохо, если бы бесконечность была отображена на (TYPE)_MAX, но это, как правило, не так - результат int x = INFINITY; равен undefined.