【问题标题】:Why are c/c++ floating point types so oddly named?为什么 c/c++ 浮点类型的命名如此奇怪?
【发布时间】:2008-12-29 23:47:26
【问题描述】:

C++ 提供三种浮点类型:float、double 和 long double。我很少在我的代码中使用浮点数,但是当我这样做时,我总是被诸如

之类的无害行上的警告所吸引
float PiForSquares = 4.0;

问题是文字 4.0 是双精度数,而不是浮点数 - 这很烦人。

对于整数类型,我们有 short int、int 和 long int,这很简单。为什么 C 没有短浮点数、浮点数和长浮点数? “double”到底是从哪里来的?

编辑:浮动类型之间的关系似乎类似于整数。 double 必须至少与 float 一样大,long double 至少与 double 一样大。没有其他精度/范围保证。

【问题讨论】:

  • 4.0 不是字符串文字;它是双重文字!
  • long float 在 double 之前存在,double 是 long float 的同义词;它已从 C89 标准中删除。
  • 我想要的是“双浮动”:)
  • <float.h> 周围有 很多 保证,特别是像 FLT_DIG 之类的东西(我认为它保证能够表示 5 个十进制数字,即从 0 到 99999 的整数)。
  • 这个SO question 也可能对名称“single”和“double”很感兴趣。

标签: c++ c floating-point history ieee-754


【解决方案1】:

术语“单精度”和“双精度”起源于 FORTRAN,并且在 C 发明时已经广泛使用。在 1970 年代早期的机器上,单精度效率明显更高,并且与今天一样,使用的内存是双精度的一半。因此它是浮点数的一个合理的默认值

long double在很久以后才添加,当时 IEEE 标准允许 Intel 80287 浮点芯片使用 80 位浮点数而不是经典的 64 位双精度.

提问者关于保证的说法不正确;今天几乎所有语言都保证以单精度(32 位)和双精度(64 位)实现 IEEE 754 二进制浮点数。有些还提供扩展精度(80 位),在C 中显示为long double。由威廉·卡汉 (William Kahan) 带头的 IEEE 浮点标准是良好工程对权宜之计的胜利:在当时的机器上,它看起来非常昂贵,但在今天的机器上,它非常便宜,而且 IEEE 浮点的可移植性和可预测性- 点数每年必须节省数十亿美元。

【讨论】:

  • OP 谈论的是 C 和 C++,它们都不能保证 IEEE 754。
  • c++有一个标志,看是否实现了ieee754:numeric_limits::is_iec559
  • 同样,C99 有 STDC_IEC_559 宏,但这些只是测试实现是否声称使用 IEEE。当 C/C++ 不保证 IEEE 浮点时,我反对的是“提问者对保证不正确”的说法。
  • 我也怀疑“几乎所有 [现代] 语言都保证实现 IEEE 754 二进制浮点数”的说法。在我使用的所有语言中,我只能想到一种我知道的可以保证这一点。
  • “单精度”并不是真正的 fortran 术语。 fortran 有/有“真实”和“双精度”。
【解决方案2】:

您可能知道这一点,但您可以制作文字浮点数/长双精度数

 float f = 4.0f;
 long double f = 4.0l;

Double 是默认设置,因为这是大多数人使用的。长双精度数可能是矫枉过正,或者浮点数的精度非常差。 Double 适用于几乎所有应用程序。

为什么要命名?有一天,我们只有 32 位浮点数(实际上我们只有定点数,但我离题了)。无论如何,当浮点成为现代架构中的一个流行特性时,C 可能是当时的主要语言,并给出了“浮点”这个名称。似乎有道理。

当时可能已经想到了double,但是在当时的cpu's/fp cpus中并没有真正实现,都是16位或者32位。一旦 double 被用于更多架构中,C 可能就会开始添加它。 C 需要一个两倍于浮点数的东西的名称,因此我们得到了一个双精度数。然后有人需要更精确,我们认为他疯了。无论如何,我们添加了它。四元组(?)这个名字有点矫枉过正。长双就够了,没有人吵闹。

部分困惑是good-ole“int”似乎随着时间而改变。过去,“int”表示 16 位整数。然而,浮点数作为 32 位 IEEE 浮点数绑定到 IEEE std。出于这个原因,C 将 float 定义为 32 位,并使用 double 和 long double 来引用更长的标准。

【讨论】:

  • 谢谢。但是如果“float”是原始类型,为什么文字是双倍的?而且我认为 IEEE 的解释很好 - 但错误:IEEE-754 发表于 85 年...
  • 那么浮点数是 1985 年之前 C 标准的一部分吗?人们很可能长期使用定点算法。
  • IIRC,32 位浮点数的术语“浮点数”和 64 位双精度数的“双数”可以追溯到 60 年代,在 C 被构想之前。可能起源于 IBM 360 架构
  • “非常糟糕的精确度” - 告诉你的显卡制造商。所有的 GPU 和基本上所有的图形都是用浮点数执行的。
  • C89 float 可能是 IEE754,但不一定。
【解决方案3】:

文字

问题是文字 4.0 是双精度数,而不是浮点数 - 这很烦人。

对于常量,整数和浮点数之间有一个重要区别。虽然决定使用哪种整数类型相对容易(您选择足够小的值来保存该值,但有符号/无符号会增加一些复杂性),但使用浮点数并不是那么容易。许多值(包括像 0.1 这样的简单值)不能用浮点数精确表示,因此类型的选择不仅会影响性能,还会影响结果值。在这种情况下,C 语言设计者似乎更喜欢稳健性而不是性能,因此他们决定默认表示应该是更准确的表示。

历史

为什么 C 没有短浮点数、浮点数和长浮点数? “double”到底是从哪里来的?

术语“单精度”和“双精度”起源于 FORTRAN,在 C 发明时就已经广泛使用。

【讨论】:

    【解决方案4】:

    首先,这些名称并非特定于 C++,但对于任何实现 IEEE 754 的浮点数据类型来说都是非常常见的做法。

    “double”这个名称是指“双精度”,而 float 通常被称为“单精度”。

    【讨论】:

    【解决方案5】:

    两种最常见的浮点格式使用 32 位和 64 位,较长的一种是第一种的“双倍”大小,因此被称为“双倍”。

    【讨论】:

      【解决方案6】:

      双精度之所以这样命名,是因为它是浮点“精度”的两倍。真的,这意味着它使用两倍的浮点值空间——如果你的浮点数是 32 位,那么你的双精度将是 64 位。

      双精度这个名字有点用词不当,因为双精度浮点数的尾数精度为 52 位,而单精度浮点数的尾数精度为 23 位(双精度为 56)。更多关于浮点的信息:Floating Point - Wikipedia,包括 底部的链接指向有关单精度和双精度浮点数的文章。

      long double 的名称很可能与整数类型的 long integer 与 short integer 的传统相同,除了在这种情况下他们颠倒了它,因为 'int' 等同于 'long int'。

      【讨论】:

        【解决方案7】:

        在定点表示中,小数点后有固定位数(十进制表示中小数点的概括)。与浮点表示相比,小数点可以在所表示的数字的数字内移动或浮动。因此得名“浮点表示”。这被缩写为“浮动”。

        在 K&R C 中,float 指的是具有 32 位二进制表示的浮点表示,double 指的是具有 64 位二进制表示的浮点表示,或者是名称的两倍大小。然而,最初的 K&R 规范要求所有浮点计算都以双精度完成。

        在最初的 IEEE 754 标准 (IEEE 754-1985)(浮点表示和算术的黄金标准)中,为单精度和双精度浮点数的二进制表示提供了定义。双精度数的名称恰如其分,因为它们的位数是单精度数的两倍。

        有关浮点表示的详细信息,请阅读 David Goldberg 的 article每个计算机科学家都应该了解浮点运算

        【讨论】:

          【解决方案8】:

          它们被称为单精度和双精度,因为它们与处理器的自然大小(不确定术语)有关。因此,32 位处理器的单精度将是 32 位长,而它的双精度将是 64 位长的两倍。他们只是决定在 C 中将单精度类型称为“float”。

          【讨论】:

          • 您正在寻找术语“字长”。
          【解决方案9】:

          double 是“双精度”的缩写。 我猜,long double 来自于不想在处理器上开始出现精度更高的浮点类型时添加另一个关键字。

          【讨论】:

            【解决方案10】:

            好的,从历史上看,它曾经是这样的:

            用于 C 的原始机器将 16 位字分成 2 个字节,一个 char 是一个字节。地址是 16 位,所以 sizeof(foo*) 是 2,sizeof(char) 是 1。int 是 16 位,所以 sizeof(int) 也是 2。然后出现了 VAX(扩展寻址)机器,地址是 32 位。一个 char 仍然是 1 个字节,但 sizeof(foo*) 现在是 4 个。

            在 Berkeley 编译器中出现了一些混乱,因此 short 现在是 2 个字节,而 int 是 4 个字节,因为它们非常适合高效的代码。 long 变成了 8 个字节,因为对于 8 字节块有一种有效的寻址方法——称为 双字。 4 字节块是 words,当然,2 字节块是 halfwords

            浮点数的实现使得它们适合单字或双字。为了保持一致,双字浮点数被称为“双精度”。

            【讨论】:

            • 我不认为这是正确的。所有这些都是整数的历史……我听说的每一个浮点历史都说“双”意味着“双精度”。
            • 另外,当然,long 的大小是错误的,使用 BSD vax 编译器当然是 4(与 int 相同)... [@ 的“等价” 987654327@ 和 long 是在将旧软件移植到 64 位(或 16 位)平台时出现大量错误的原因]
            【解决方案11】:

            需要注意的是,double 不必能够保持比float 更大的值;它只需要更精确

            【讨论】:

            • 我不认为它必须更精确:它必须“不那么精确”,这是相当不同的......
            • 标准给它一个较小的 epsilon。我认为 1E-5 与 1E-7。
            【解决方案12】:

            因此 %f 用于浮点类型,%lf 用于长浮点,与双精度相同。

            【讨论】:

            • 在 C 的 printf 函数中,%f 已经代表 double,而 %Lf 代表 long double。对于scanf 函数,您是正确的。
            猜你喜欢
            • 1970-01-01
            • 2017-02-01
            • 1970-01-01
            • 1970-01-01
            • 2015-12-18
            • 1970-01-01
            • 2020-01-14
            • 1970-01-01
            • 2015-09-24
            相关资源
            最近更新 更多