Разница между сужением и усечением в C ++? - PullRequest
3 голосов
/ 08 апреля 2020

Я изучал книгу (язык программирования C ++, Страуструп, 4-е издание). Пример, приведенный в разделе, связанном с инициализацией, приведен ниже:

void f(double d, int i)
{
    int a{ d };     // error : possible truncation
    char b{ i };    // error : possible narrowing
}

В чем именно разница между усечением и сужением?

Ответы [ 4 ]

5 голосов
/ 08 апреля 2020

Сужающее преобразование - это, в основном, любое преобразование, которое может привести к потере информации. Строго говоря, сужающее преобразование - это:

неявное преобразование

  • из типа с плавающей точкой в ​​целочисленный тип или
  • от long double до double или float, или от double до float, за исключением случаев, когда источником является постоянное выражение, а фактическое значение после преобразования находится в диапазоне значений, которые могут быть представлены (даже если они не могут быть представлены точно) или
  • из целочисленного типа или перечислимого типа с незаданной областью в тип с плавающей запятой, за исключением случаев, когда источником является константное выражение, а фактическое значение после преобразования будет соответствовать целевому типу и получит исходное значение, когда преобразованный обратно в исходный тип или
  • из целочисленного типа или перечислимого типа с незаданной областью в целочисленный тип, который не может представлять все значения исходного типа, кроме случаев, когда источником является константное выражение, значение которого после интегральных повышений будет соответствовать типу цели, или
  • от Тип inter или указатель на член типа bool.

Обратите внимание, что это означает, что обе опубликованные вами конверсии сужают конверсию. int a{ d }; - первый случай, а char b{ i }; - четвертый.

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

2 голосов
/ 08 апреля 2020

Какая разница между усечением и сужением?

Усечение сокращает десятичное значение, такое как float или double, до его интегральная форма int с битами дополнительной точности после удаления десятичной дроби (от 2 -1 в соответствующей десятичной форме).

A double может быть усечено до float также с возможностью переполнения (в зависимости от размера значения) и удаления половины битов точности в его двоичной форме (поскольку double имеет удвоенную точность с плавающей запятой, причем они обычно равны 64 и 32-битным плавающим точкам соответственно ).

Для примера усечения double в float рассмотрим что-то, что идет по крайней мере выше 23 прецизионных бит (с учетом мантиссы с плавающей запятой), такое как значение PI, относительно которого BenVoigt привел пример в комментариях.

Значение PI, заданное двойным, равно:

11.001001000011111101101010100010001000010110100011000
// 3.141592653589793116

Обратите внимание, что имеется 52 прецизионных бита (согласно стандарту IEEE 754, от 0 до 51), или биты, формирующие значение после десятичного числа.

Соответствующее усеченное значение с плавающей запятой:

11.0010010000111111011011
// 3.1415927410125732422

Обратите внимание на неточность значения PI в относительном выражении числа, рассмотренного выше. Это вызвано удалением конечных битов точности при усечении значения с double до float (в котором только 23 прецизионных бита, от 0 до 22), что обычно уменьшает точность битов в этом случае.

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

Сужение означает сокращение значения в качестве имени также подразумевает, но в отличие от усечения это не ограничивается сокращением значения с плавающей запятой до целочисленного значения. Это относится и к другим преобразованиям, таким как long в int, тип указателя на логическое значение и символ в целое число (как в вашем примере).

1 голос
/ 08 апреля 2020

Возможно, это лучше всего понять на примере ...

Допустим, d == 3.1415926, тогда в вашем коде a будет иметь вид 3. Это усечение.

С другой стороны, если i == 1000, то это вне диапазона char. Если char равно unsigned, значение будет изменено, и вы получите 1000%256 в качестве значения b. Это происходит потому, что int имеет более широкий диапазон, чем char, поэтому это преобразование называется сужением.

0 голосов
/ 08 апреля 2020
double d=2.345;
int a = d; // a is 2 now, so the number 2.345 is truncated

Что касается int - char, то char имеет размер 1 байт, в то время как int имеет 4 байта (в предположении 32 бита), поэтому вы будете "сужать" переменную i.

Это может быть примерно по-английски sh :) Вы можете посмотреть слова в словаре, чтобы они были понятнее.

...