C ++中缩小和截断之间的区别?

Difference between narrowing and truncation in C++?

我一直在浏览一本书(C++ 编程语言 Stroustrup 第 4 版)。 与初始化相关的部分中给出的示例如下:

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

截断和缩小到底有什么区别?

double d=2.345;
int a = d; // a is 2 now, so the number 2.345 is truncated

至于intcharchar有1个字节,而int有4个字节(假设32位),所以你会"narrowing"变量i.

可能只是英文:)你可以查字典,这样可能更清楚。

也许最好用一个例子来理解...

假设 d == 3.1415926 那么在您的代码中 a 将最终成为 3。那就是截断。

另一方面,如果 i == 1000 则超出了 char 的范围。如果 charunsigned,该值将回绕,您将得到 1000%256 作为 b 的值。发生这种情况是因为 int 的范围比 char 更宽,因此这种转换称为缩小范围。

缩小转换基本上是任何可能导致信息丢失的转换。严格来说,narrowing conversion 是:

an implicit conversion

  • from a floating-point type to an integer type, or
  • from long double to double or float, or from double to float, except where the source is a constant expression and the actual value after conversion is within the range of values that can be represented (even if it cannot be represented exactly), or
  • from an integer type or unscoped enumeration type to a floating-point type, except where the source is a constant expression and the actual value after conversion will fit into the target type and will produce the original value when converted back to the original type, or
  • from an integer type or unscoped enumeration type to an integer type that cannot represent all the values of the original type, except where the source is a constant expression whose value after integral promotions will fit into the target type, or
  • from a pointer type or a pointer-to-member type to bool.

请注意,这意味着您发布的两次转化都是缩小转化。 int a{ d };是第一种,char b{ i };是第四种。

只有在浮点型和整型之间转换时才会出现截断。一般指浮点数的小数部分丢失(source)。这意味着截断是缩小转换的子集。

What exactly is the difference between truncation and narrowing?

Truncation 将基于小数的值(例如 floatdouble 缩短为其具有额外精度的整数形式 int删除小数点后的位(从 2-1 中相应的十进制形式)。

A double 也可以被截断为 float,有可能发生溢出(取决于值的大小)并删除其二进制形式的一半精度位(因为 double 的精度是 float 的两倍,它们通常分别是 64 位和 32 位浮点数)。

对于 double 被截断为 float 的示例,考虑至少超过 23 个精度位(考虑浮点数的尾数)的东西,例如 PI 的值,关于 BenVoigt在评论中举了一个例子。

double给出的PI值为:

11.001001000011111101101010100010001000010110100011000
// 3.141592653589793116

注意这里有52个精度位(根据IEEE 754标准,从0到51),即小数点后的值。

对应的截断浮点值:

11.0010010000111111011011
// 3.1415927410125732422

请注意,相对于上述数字而言,PI 值不准确。这是由于在将值从 double 截断到 float(只有 23 个精度位,从 0 到 22)时删除了尾部精度位,在这种情况下按顺序降低精度位.

在将浮点值转换为整数形式之后,您可以说它的行为类似于 floor 函数调用。

Narrowing 顾名思义就是缩短值,但与截断不同的是,它不限于将浮点值缩短为整数值。它也适用于其他转换,例如 longint、指针类型到布尔值和字符到整数(如您的示例)。