【问题标题】:Difference between narrowing and truncation in C++?C ++中缩小和截断之间的区别?
【发布时间】:2020-07-21 04:39:04
【问题描述】:

我一直在阅读一本书(C++ Programming Language Stroustrup 第 4 版)。 与初始化相关的部分给出的示例如下:

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

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

【问题讨论】:

  • 缩小浮点数的字符截断 -> 整数?想想就差不多了
  • @AlanBirtles,是否有关于这两个词的通用解释,而不仅仅是在上面的示例代码上下文中?

标签: c++ c++11 initialization truncation narrowing


【解决方案1】:

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

截断将基于十进制的值(例如 floatdouble)缩短为其整数形式 int,并在小数点后加上额外的精度位(从 2- 1 对应的十进制形式)删除。

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

对于double 被截断为float 的示例,请考虑至少超过 23 个精度位(考虑浮点数的尾数)的值,例如 PI 的值,BenVoigt 在 cmets 中给出了一个示例.

double 给出的 PI 值为:

11.001001000011111101101010100010001000010110100011000
// 3.141592653589793116

请注意,有 52 个精度位(根据 IEEE 754 标准,从 0 到 51),或者是形成小数点后值的位。

对应的截断浮点值:

11.0010010000111111011011
// 3.1415927410125732422

请注意 PI 值相对于上述数字的不准确性。这是由于在将值从 double 截断到 float(只有 23 个精度位,从 0 到 22)时删除了精度的尾随位,在这种情况下通常会降低精度位。

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

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

【讨论】:

  • double->float 还涉及截断(并可能溢出)
  • @BenVoigt 已更正,截断的最终结果是整数值还是浮点数? (会发生溢出)
  • 也想确定 - 截断仅指从浮点值转换,还是也可以从非十进制值转换,例如从 int 到 @ 987654336@?
  • 这将是一个新的浮点值,但具有较少的尾随位精度。 “截断”只是意味着删除一些精度。截断通常发生在整数边界(“小数点”),但并非必须如此。
  • 从 int 到 short 通常会丢失最重要的位(对于 unsigned intunsigned short 保证会这样做),因此它仅对范围的精度没有影响。这不是截断,因为您不会丢失尾随位。
【解决方案2】:

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

隐式转换

  • 从浮点类型到整数类型,或
  • 从long double到double或者float,或者从double到float,除非源是常量表达式并且转换后的实际值在可以表示的值范围内(即使不能准确表示) , 或
  • 从整数类型或无作用域枚举类型到浮点类型,除非源是常量表达式并且转换后的实际值将适合目标类型并在转换回原始值时会产生原始值输入,或
  • 从整数类型或无作用域枚举类型到不能表示原始类型的所有值的整数类型,除非源是常量表达式,其值在整数提升后将适合目标类型,或
  • 从指针类型或指向成员的指针类型到 bool。

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

仅在浮点类型和整数类型之间转换时才会发生截断。它通常是指丢失的浮点数的小数部分(source)。这意味着截断是缩小转换的子集。

【讨论】:

  • 谢谢,这让我明白了。只是另一个查询,c++ 标准是否提到了这两个词中的任何一个?
  • @pasha 我的答案中的两个链接都是指向 c++ 标准中这些术语的定义的直接链接。在此重复:narrowing conversiontruncation
  • 我的错,我以为这只是github上的一些文件,再次感谢
  • @pasha 从技术上讲,它只是 github 上的一些文档。它不是该标准的官方发布版本。这是该标准下一版本的最新工作草案。但它是免费的,而且仍然非常准确,它最后一次更新是星期五。
【解决方案3】:
double d=2.345;
int a = d; // a is 2 now, so the number 2.345 is truncated

对于intcharchar 的大小为 1 字节,而int 的大小为 4 字节(假设为 32 位),因此您将“缩小”变量 i

它可能只是英语:)你可以在字典中查找单词,这样可能会更清楚。

【讨论】:

    【解决方案4】:

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

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

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

    【讨论】:

      猜你喜欢
      • 2010-09-13
      • 2021-07-15
      • 2011-01-29
      • 1970-01-01
      • 2013-05-02
      • 2014-02-03
      • 1970-01-01
      • 2022-08-20
      • 1970-01-01
      相关资源
      最近更新 更多