Я хочу быть лучше, зная, когда мне следует сыграть. Каковы неявные правила преобразования типов в C ++ при сложении, умножении и т. Д. Например,
int + float = ?
int * float = ?
float * int = ?
int / float = ?
float / int = ?
int / int = ?
int ^ float = ?
и так далее ...
Будет ли выражение всегда оцениваться как более точный тип? Различаются ли правила для Java? Пожалуйста, поправьте меня, если я сформулировал этот вопрос неточно.
^
это XOR.Ответы:
В C ++ операторы (для типов POD) всегда действуют на объекты одного типа.
Таким образом, если они не совпадают, один будет повышен, чтобы соответствовать другому.
Тип результата операции совпадает с операндами (после преобразования).
Заметка. Минимальный размер операций составляет
int
. Поэтомуshort
/char
повышаются доint
того, как операция завершена.Во всех ваших выражениях
int
символ повышается доfloat
до выполнения операции. Результатом операции являетсяfloat
.источник
char
тип. Если значениеchar + char
присваивается achar
, то он может просто выполнить арифметикуchar
и, например, обернуть. Но если результат присваивается,int
тогда он должен выполнять арифметику в типе, достаточно большом, чтобы получить правильный результат, когда он больше, чемCHAR_MAX
.((int) 4) - ((unsigned int) 5)
приводит4294967295
к 32-битным и 32-битным беззнаковым.Арифметические операции, связанные с
float
результатами вfloat
.Для более подробного ответа. Посмотрите, что говорится в разделе §5 / 9 стандарта C ++.
источник
double
ни другимlong double
.long long
иunsigned long
не адресовано прямо здесь.float
не хватает битов в мантиссе (24 бита для IEEE-754 ) для 32-битногоint
, поэтому возможна некоторая потеря данных. 64-битныйdouble
должен быть просто в порядке.Поскольку другие ответы не говорят о правилах в C ++ 11, вот один. Из стандарта C ++ 11 (черновик N3337) §5 / 9 (подчеркнуто отличие):
Смотрите здесь список, который часто обновляется.
источник
Этот ответ в значительной степени направлен на комментарий, сделанный @ RafałDowgird:
Имейте в виду, что стандарт C ++ имеет важнейшее правило «как будто». Смотрите раздел 1.8: Выполнение программы:
Компилятор не может установить
int
размер 8 бит, даже если бы он был самым быстрым, поскольку стандарт предписывает 16-битный минимумint
.Следовательно, в случае теоретического компьютера со сверхбыстрыми 8-битными операциями неявное повышение до
int
арифметики может иметь значение. Однако для многих операций вы не можете определить, действительно ли компилятор выполнял операции с точностью до aint
и затем преобразовывал их в achar
для хранения в вашей переменной, или все эти операции выполнялись в char.Например, рассмотрим
unsigned char = unsigned char + unsigned char + unsigned char
, где сложение будет переполнено (допустим, значение 200 для каждого). Если бы вы повысили доint
, вы бы получили 600, что затем было бы неявно приведено к результатуunsigned char
, который обернул бы по модулю 256, таким образом, получив окончательный результат 88. Если вы не делали таких повышений, вам пришлось бы переходить между первым два дополнения, которые уменьшают проблему с200 + 200 + 200
до144 + 200
344, что уменьшает до 88. Другими словами, программа не знает разницы, поэтому компилятор может игнорировать мандат на выполнение промежуточных операций,int
если операнды имеют более низкий рейтинг, чемint
.Это верно в общем случае сложения, вычитания и умножения. Это вообще не верно для деления или модуля.
источник
Если исключить неподписанные типы, существует упорядоченная иерархия: знаковый символ, short, int, long, long long, float, double, long double. Во-первых, все, что идет перед int в приведенном выше, будет преобразовано в int. Затем в бинарной операции тип с более низким рейтингом будет преобразован в более высокий, и в результате будет получен тип с более высоким рейтингом. (Вы заметите, что из иерархии, каждый раз, когда речь идет о плавающей точке и интегральном типе, целочисленный тип будет преобразован в тип с плавающей точкой.)
Неподписанные вещи немного усложняют: это мешает ранжированию, и части ранжирования становятся определяемыми реализацией. Из-за этого лучше не смешивать подписанные и неподписанные в одном выражении. (Кажется, что большинство экспертов по C ++ избегают использования без знака, если только не используются побитовые операции. Это, по крайней мере, то, что рекомендует Страуструп.)
источник
int
для числа, которое никогда не должно быть отрицательным, является полной тратой полных 50% доступного диапазона. Я конечно не Страуструп, но я используюunsigned
по умолчанию иsigned
только тогда, когда у меня есть причина.bool in_order(vector<T> vec) { for ( int i = 0; i < size() - 1; ++i) { if (vec[i + 1] < vec[i]) return false; } return true;
и тогда вы будете раздражены, обнаружив, что он падает для пустых векторов, потому что size () - 1 возвращает 18446744073709551615.Мое решение к проблеме получил WA (неправильный ответ), то я изменил одну из них,
int
чтобыlong long int
и он дал AC (принять) . Раньше я пытался это сделатьlong long int += int * int
, а после я исправлял этоlong long int += long long int * int
. Погуглил я придумал,1. Арифметические преобразования
Условия для преобразования типов:
Условия выполнены ---> Конверсия
Любой операнд имеет тип long double . ---> Другой операнд преобразуется в тип long double .
Предыдущее условие не выполнено, и любой из операндов имеет тип double . ---> Другой операнд преобразуется в тип double .
Предыдущие условия не выполнены, и любой из операндов имеет тип float . ---> Другой операнд преобразуется в тип float .
Предыдущие условия не выполнены (ни один из операндов не имеет плавающих типов). ---> Интегральные продвижения выполняются над операндами следующим образом:
2 Целочисленные правила преобразования
Целочисленные типы, меньшие чем int, повышаются, когда над ними выполняется операция. Если все значения исходного типа могут быть представлены как int, значение меньшего типа преобразуется в int; в противном случае он конвертируется в беззнаковое целое. Целочисленные продвижения применяются как часть обычных арифметических преобразований для определенных выражений аргументов; операнды унарных операторов +, - и ~; и операнды операторов сдвига.
Целочисленный рейтинг конверсии:
long long int
должен быть больше, чем рангlong int
, который должен быть больше, чем рангint
, который должен быть больше, чем рангshort int
, который должен быть больше, чем рангsigned char
.char
должно равняться званиюsigned char
иunsigned char
.Обычные арифметические преобразования:
источник
Вся глава 4 рассказывает о конверсиях, но я думаю, что вы должны быть в основном заинтересованы в них:
4.5 Интегральные продвижения [conv.prom] r-значение
типа char, знаковый char, unsigned char, short int или unsigned short int может быть преобразовано в r-значение типа int, если int может представлять все значения типа источника; в противном
случае исходное значение может быть преобразовано в значение типа unsigned int.
Значение типа wchar_t (3.9.1) или тип перечисления (7.2) может быть преобразовано в значение первого
из следующих типов, которые могут представлять все значения его базового типа: int, unsigned int,
long или unsigned длинный.
Значение r для интегрального битового поля (9.6) может быть преобразовано в значение типа int, если int может представлять все
значения битового поля; в противном случае его можно преобразовать в unsigned int, если unsigned int может
повторно передать все значения битового поля. Если битовое поле еще больше, к нему не применяется интегральное продвижение. Если
битовое поле имеет перечисляемый тип, оно рассматривается как любое другое значение этого типа в целях продвижения.
Rvalue типа bool может быть преобразовано в rvalue типа int, где false становится равным нулю, а true
становится единым.
Эти преобразования называются интегральными продвижениями.
4.6 Повышение с плавающей запятой [conv.fpprom] Значение r
с типом float может быть преобразовано в значение типа double. Значение не изменяется.
Это преобразование называется продвижением с плавающей запятой.
Поэтому все преобразования, включающие float - результат float.
Только тот, который включает оба int - результатом является int: int / int = int
источник
Тип выражения, если не обе части имеют одинаковый тип, будет преобразован в наибольшую из обеих. Проблема здесь в том, чтобы понять, какой из них больше другого (он не имеет ничего общего с размером в байтах).
В выражениях, в которых участвуют действительное число и целое число, целое число будет преобразовано в действительное число. Например, в int + float тип выражения является float.
Другое различие связано с возможностями типа. Например, выражение, включающее int и long int, будет иметь тип long int.
источник
long
"больше", чем,float
но какой типlong
+float
?Предостережение!
Преобразования происходят слева направо.
Попробуй это:
источник
j + i * k
приведет к 101.